自定义类型 是一种新的 类型 而类型别名 还是原来的 类型 不过起了一个别名而已
//自定义新的类型
type Myint int
//类型别名
type intAli = int
func main() {
// 分别打印其类型
var t1 Myint
var t2 intAli
of1 := reflect.TypeOf(t1)
fmt.Println(of1)
of2 := reflect.TypeOf(t2)
fmt.Println(of2)
fmt.Println()
}
//输出结果
main.Myint
int
// 自定义函数类型
type myMethod func(int, string) string
注意 : 任何满足拥有相同形参列表 和 返回值的 函数 都可以视为 是我们自定义的函数类型
// 自定义函数类型
type myMethod func(int, string) string
m1 := func(i1 int, s1 string) string {
itoa := strconv.Itoa(i1)
return itoa + s1
}
var m2 myMethod
m2 = m1
跟Java一样 Go 语言中的接口 也是定义了一个对象的行为规范,只定义规范不实现,由具体的对象来实现规范的细节
但与Java不同的是 Go语言中的接口是非侵入式的 而Java则必须显示的声明
Go也同样倡导面向接口编程
在Go语言中接口(interface)是一种类型,一种抽象的类型。
interface是一组method的集合,接口做的事情就像是定义一个协议(规则),不关心对方是什么类型,只关心对方能做什么。这是duck-type programming的一种体现,只要一个物体能像鸭子一样叫那我们就可以称它为鸭子;只要一个软件能存储和查询数据我们就可以称它为数据库;只要一台机器有洗衣服和甩干的功能我们就可以称它为洗衣机。
为了保护你的Go语言职业生涯,请牢记接口(interface)是一种类型。
type 接口名 interface{
方法名一(参数一,参数二...) 方法返回值
方法名二(参数一,参数二...) 方法返回值
}
一个结构体 实现了 这个接口的所有方法 就是实现了这个接口 少一个方法 或者 返回值类型不一致 都不是这个接口的实现类型
如下列代码所示 :
结构体 woman 和 man 实现了 say() 和 eat() 方法 此时就是实现了 human接口
所有我们可以 定义一个 human类型 用来接受 woman 和 man 类型
// 定义一个接口
type human interface {
//接口是一组方法的集合
say()
eat()
}
//定义两个接口的实现类型
type woman struct {
name string
age int
sex string
}
type man struct {
name string
age int
sex string
}
//实现 接口中的所有 方法 即实现了该接口
func (w woman) say() {
fmt.Println("男人说话雄厚")
}
func (w woman) eat() {
fmt.Println("女人吃饭慢吞吞")
}
func (m man) say() {
fmt.Println("女人说话甜美")
}
func (m man) eat() {
fmt.Println("男人吃饭狼吞虎咽")
}
如果 类的的方法以指针接收者实现接口的时候,只有 该类的指针才被认为实现了该接口
只要该接口中 任何一个方法是指正接收者 就必须是类的指针 才是 接口的实现 变量
// 定义一个接口
type human interface {
//接口是一组方法的集合
say()
eat()
}
// 定义一个结构体
type man struct {
name string
age int
sex string
}
//实现 接口中的所有 方法 即实现了该接口\
// 注意 绑定的是 结构体的指针
func (w *woman) say() {
fmt.Println("男人说话雄厚")
}
func (w *woman) eat() {
fmt.Println("女人吃饭慢吞吞")
}
// 因为 接口方法是 指针接收者 所以 是 结构体的指针实现了该接口
var w1 human = &woman{
name: "静香",
age: 18,
sex: "女",
}
一个类型可以实现多个接口 , 一个接口同样的也能被多个类型所实现
// 接口嵌套 嵌套了两个接口类型 一个 teacher 和 一个 student 接口
type school interface {
teacher
student
}
type teacher interface {
say()
}
type student interface {
study()
}
//定义一个类型
type hman struct {
name string
age int
}
// 使用该类型作为方法的接受者 分别实现两个接口 等同于实现了这个接口
func (h hman) say() {
fmt.Println("老师上课讲课")
}
func (h hman) study() {
fmt.Println("学生上课学习")
}
func main() {
//是否能用接口类型接收 测试
// 定义一个接口类型
var schhum school = hman{
name: "张三",
age: 19,
}
schhum.say()
//interfaceMethod()
}
一个包可以简单理解为一个存放 .go文件的文件夹 。 该文件夹下面的所有Go文件都要在代码的第一行添加如下代码,声明该文件归属的包
注意事项 :
如果想在一个包中引用另外一个包里的标识符 ( 如 变量,常量,类型,函数 )时,该 标识符必须是对外可见的. 类似于 Java中的 public 而在 Go 中 只需要将标识符首字母大写即可
在结构体中 某个字段的首字母是小写 则对于其他包来书 该字段是不可见的
//可见常量
const Sex string = "男"
// 不可见 常量
const age int = 19
//可见 函数
func CanSee() {
fmt.Println("你看到了我")
}
// 不可见函数
func notCanSee() {
fmt.Println("背起了行囊")
}
//可见结构体
type Human struct {
// 可序列化
Name string
// 不可序列化 不可见
age string
}
// 不可见结构体
type student struct {
date string
}
如果需要使用其他包下的标识符 需要导入此包 语法如下
import "包的路径"
注意事项 :
在导入包的同时 我们还可以为包设置别名 . 设置别名通常用于包名过长或者导入的包名重入的情况
import 别名 "包的路径"
如果只需要导入包而不需要使用包中的数据 可以使用匿名包 等同于 自定义包名的时候 起了一个 隐匿的名字
import _ "包的路径"
Go 语言 执行导包语句时 会自动执行被导入包的 init 函数
注意事项

当 导包 存在一个 层级 嵌套 的时候 最后被导入的包的 init 函数将最先被执行

package calc
//加法
func Sum(x int, y int) int {
return x + y
}
//减法
func Sub(x int, y int) int {
return x - y
}
// 乘法
func Mult(x int, y int) int {
return x * y
}
//除法
func Div(x int, y int) int {
return x / y
}
package main
//导入calc包
import (
//包起别名
"fmt"
cl "go_todo/calc"
)
func main() {
// 做加法
sum := cl.Sum(1, 9)
fmt.Printf("两数相加的结果为 %d \n", sum)
//做减法
sub := cl.Sub(100, 99)
fmt.Printf("两数相减的结果为 %d \n", sub)
//做乘法
x, y := 5, 20
mult := cl.Mult(x, y)
fmt.Printf("%d 乘 %d = %d \n", x, y, mult)
x, y = 100, 4
div := cl.Div(x, y)
fmt.Printf("%d 除 %d = %d \n", x, y, div)
}