struct
struct(结构体)的定义
struct(结构体)是一种聚合类型,里面可以包含任何类型的值,这些值就是我们定义的结构的成员,也称为字段
关键字和声明
type+struct
1 2 3 4 type structName struct { fieldName typeName ... }
示例
1 2 3 4 type person struct { name string age uint }
使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 type person struct { name string age uint addr address } type address struct { province string city string } func main () { user := person{name: "JunNanZeng" , age: 18 , addr: address{province: "浙江省" , city: "玉环市" }} fmt.Println(user.name) fmt.Println(user.addr.city) }
结构体里面值的类型可以为结构体
给变量赋值结构体时内容可以为空,这样所有字段为空
由于golang没有python和c++那样的class用来定义类,所以在golang中,可以使用结构体完成面对对象
interface
interface(接口)的定义
interface(接口)是与调用方的一种约定,它是一个高度抽象的类型,不用与具体的实现细节绑定在一起。接口要做的是定义好约定,告诉调用方自己可以做什么,但调用方不用直到它内部的实现,这与我们见到的具体类型如int, map, slice等不一样。
关键字和声明
关键字type interfaceName interface
1 2 3 type Stringer interface { String() string }
告诉调用者使用String()方法获得一个字符串
接口实现
之前,我们不能直接打印出结构体的内容,现在我们可以定义我们结构体要输出的内容了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 type person struct { name string age uint addr address } type address struct { province string city string } type Stringer interface { String() string } func (p person) String() string { return fmt.Sprintf("the name is %s, age is %d" , p.name, p.age) } func (addr address) String() string { return fmt.Sprintf("the province is %s, city is %s" , addr.province, addr.city) } func PrintString (s Stringer) { fmt.Println(s.String()) } func main () { user := person{ name: "JunNanZeng" , age: 18 , addr: address{ province: "浙江省" , city: "玉环市" }} PrintString(user) PrintString(user.addr) }
个人理解
接口其实就是一个中转站,这里放着可以调用的方法,然后结构体,类等要实现对应的方法,否则无法编译通过。
只要接口的约定不变,接口的实现者可以更好地升级重构。
值和指针类型接收者
在实现方法的时候,不仅结构体的值类型接收者会实现接口,结构体的指针类型接收者也会实现接口
1 2 3 4 5 6 7 func main () { p := &user PrintString(user) PrintString(p) }
将person方法string中值接收者改成指针接收者
1 2 3 4 5 6 func (p *person) string () string { return fmt.Sprintf("the name is %s, age is %d" , p.name, p.age) }
此时我们运行以下代码,将报错
1 2 3 func main () { PrintString(user) }
报错信息
1 2 can not use user (type person) as type Stringer in argument to PrintString: person does not implement Stringer (String method has pointer receiver )
想要编译通过就要修改一下代码
1 2 3 4 func main () { p := &user PrintString(p) }
报错的原因:
将person方法string值接收者改成指针接收者,此时接口只实现指针的Stringer的接口,没有实现值的接口
值类型接收者和指针类型接收者的接口实现规则
方法接受者
实现接口的类型
(p person)
person 和 *person
(p *person)
*person