持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情
结构体
结构体是一种聚合类型,里面可以包含任意类型的值(结构体的成员,即字段)。
type structName struct{
fieldName typeName
....
....
}
定义结构体,使用关键字 type 和 struct ,变量名在前,类型在后。在结构体内变量名称为成员名或字段名。在 Go 中也支持空结构体,即没有字段。
结构体类型和普通的字符串、整型一样,也可以使用同样的方式声明和初始化。如下例子,声明 person 类型的变量p,没有初始化则默认使用结构体里字段的零值。声明并初始化了变量p2,有了初始化的值就可以使用了。
type person struct{
name string
age p
}
var p person
p2 :=person{'Tom',18}
// 使用
fmt.Println(p2.name,p2.age)
结构体支持嵌套使用。因结构体的字段允许是任意类型,所以也包括自定义的结构体类型。如示例所示:
type person struct {
name string
age uint
addr address
}
type address struct {
province string
city string
}
接口
接口是调用方的一种约定,是一种高度抽象的类型,不用和具体的实现细节绑定在一起。
type name interface {
method1()
method2() string
......
}
定义接口,使用关键字 type 和 interface 。所以其表示自定义的类型是一个接口。接口内允许有多个方法,只是表示接口的约定,具体的方法是如何实现的,接口不关心,只有接口的实现者关心。
实现者如何实现接口?
type person struct{
name string
age int
}
type PersonAction interface {
sayHi()
}
func (p person) sayHi() {
fmt.println('hi,world')
}
接口的实现者必须是一个具体的类型,以上示例中,给结构体 person 类型定义一个方法,这个方法和接口中的方法的签名(方法名,参数,返回值)一样,这样结构体 person 就实现了PersonAction 接口。如果接口有多个方法,那必须实现接口所有的方法才算实现了接口。
在学习方法的时候说到,方法必须要有接受者,接收者可以是值接收者或者指针接收者,那么在实现接口的时候值类型和指针类型有什么区别?
先说结论:
- 以值类型接收者实现接口的时候,不管是类型本身,还是该类型的指针类型,都实现了该接口
- 以指针类型接收者实现接口时候,只有对应的指针类型才被认为是实现了该接口
具体证明,可以查看下面的例子:
//1、值类型接收者实现接口
func (p person) sayHi() {
fmt.println('hi,world')
}
// 使用时
p.sayHi() // 输出 hi,world
&p.sayHi() //输出 hi,world
// 2、指针类型接收者实现接口
func (p *person) sayHi() {
fmt.println('hi,world')
}
// 使用
&p.sayHi() //输出 hi,world
p.sayHi() // 报错 ,因为指针类型作为接收者,只有对应指针类型实现了该接口,所以会报错