您诸位好啊,我是无尘,今天跟大家介绍下Go结构体和接口都实现了哪些功能?
结构体是种聚合类型,里面可以包含任意类型的值,这些值就是结构体的成员,或成为字段,定义结构体,需要使用 「type+struct」 关键字组合
type person struct { //人结构体
name string //人的名字
age uint //人的年龄
}
var p person
❝声明了一个person类型的变量p,但是没有初始化,所以默认使用结构体里字段的零值。 ❞
p := person{"无尘",18}
❝表示结构体变量 p 的name字段初始化为“无尘”,age字段初始化为18。顺序必须和字段定义顺序一致。 ❞
p := person{age:18,name:"无尘"}
❝像这样指出字段名,就可以打乱初始化字段的顺序。也可以只初始化其中部分字段,剩余字段默认使用零值:
p := person{age:30}
❞
结构体字段可以是任意类型,包括自定义的结构体类型:
type person struct { //人结构体
name string
age uint
addr address //使用自定义结构体类型
}
type address struct { //地址结构体
city string
}
对于这样嵌套结构体,初始化和一般结构体类似,根据字段对应的类型初始化即可:
p := person {
age:18,
name:"无尘",
addr:address{
city:"北京",
},
}
结构体的字段和调用一个类型的方法一样,都是使用点操作符“.”:
fmt.Println(p.age)
//访问嵌套结构体里的city字段的值:
fmt.Println(p.addr.city)
接口是一个抽象的类型,是和调用方的一种约定。接口只需要定义约定,告诉掉用方可以做什么,而不用知道它的内部实现。 接口的定义是 「type + interface」关键字类实现。
//Info 是一个接口,它有方法 Getinfo()string
type Info interface {
Getinfo() string
}
❝对应 Stringer 接口,它会告诉调用者可以通过 String()放获取一个字符串,这就是接口的约定,而这个字符串是怎么获取到的,接口并不关心,调用者也不用关心,因为这些是接口的实现者来处理的。 ❞
接口的实现者必须是一个具体的类型:
func (p person) Getinfo() string {
return fmt.Sprintf("my name is %s,age is %d",p.name,p.age)
}
我们先定义一个可以打印 Info 接口的函数:
func printInfo(i Info) {
fmt.Println(i.Getinfo())
}
printInfo(p)
//结果为:my name is 无尘,age is 18
❝因为 person 类型实现了Info接口,所以变量p可以作为函数printInfo的参数。 ❞
上面接口体person实现了Info接口,是否结构体指针也实现了该接口呢?
printInfo(&p)
测试发现p的指针作为参数函数也是可以正常运行,表明「以值类型接收者实现接口,类型本身和该类型的指针类型,都实现了该接口」
那么把接收者改成指针类型:
func (p *person) Getinfo() string {
return fmt.Sprintf("my name is %s,age is %d",p.name,p.age)
}
然后再调用函数 printInfo(p)
,代码编译不通过,表明「以指针类型接收者实现接口,只有对应的指针类型才被认为实现了接口」
方法接收者 | 实现接口类型 |
---|---|
(p person) | person和*person |
(p *person) | *person |
有什么问题,可以公众号内回复或加我微信交流。