9.1 结构体

结构体是值类型,所以也可以用new来创建。
结构体中,字段名是唯一的。
Go中没有面向对象语言中的类,而结构体struct实现了类似的功能。所以可以把结构体struct想象成一个没有方法的轻量级的类。
声明:

  1. type myst struct {
  2. name string
  3. age int
  4. sex bool
  5. }

初始化:

  1. s := myst{} //初始化
  2. s1 := new(myst) //分配内存
  3. fmt.Println(s) //返回字段的零值{ 0 false}
  4. fmt.Println(s1) //返回内存的指针&{ 0 false}

结构体支持嵌套,也就是结构体的字段也可以是结构体。

9.1.1 工厂模式

  1. package main
  2. import "fmt"
  3. //定义一个结构体
  4. type myst struct {
  5. name string
  6. age int
  7. sex bool
  8. }
  9. //定义一个工厂,就是一个函数
  10. func me(name string, age int, sex bool) *myst {
  11. return &myst{ //返回指针
  12. name: name,
  13. age: age,
  14. sex: sex,
  15. }
  16. }
  17. func main() {
  18. myinfo := me("吴彦祖", 18, true) //调用
  19. fmt.Println(*myinfo) //{吴彦祖 18 true
  20. }

如果不适用工厂模式,上述怎么写:

  1. package main
  2. import "fmt"
  3. //定义一个结构体
  4. type myst struct {
  5. name string
  6. age int
  7. sex bool
  8. }
  9. //定义一个工厂
  10. func me(name string, age int, sex bool) *myst {
  11. m := myst{
  12. name: name,
  13. age: age,
  14. sex: sex,
  15. }
  16. return &m
  17. }
  18. func main() {
  19. myinfo := me("吴彦祖", 18, true) //调用
  20. fmt.Println(*myinfo) //{吴彦祖 18 true
  21. }

可以发现,就是少了实例化结构体而已。

9.1.2 匿名和内嵌结构体

结构体内的字段可以没有名字,只有类型,类型是必须的。
一个结构体内,同一种类型的匿名字段,只能有一个。
结构体可以内嵌套娃的,以此来实现类似于面向对象的继承。

  1. package main
  2. import "fmt"
  3. type myst struct {
  4. name string "这是字段的标签" //姓名
  5. age int //年龄
  6. sex bool //性别
  7. }
  8. type myst2 struct {
  9. int //匿名字段,身高
  10. m myst //结构体类型
  11. }
  12. func main() {
  13. myinfo := myst2{ //实例化
  14. 188, //匿名字段
  15. myst{ //内嵌结构体
  16. name: "吴彦祖",
  17. age: 18,
  18. sex: true,
  19. },
  20. }
  21. fmt.Println(myinfo) //{188 {吴彦祖 18 true}}
  22. }

9.2 方法

结构体就像面向对象中的简化的类,自然也有类方法。
Go中的方法是作用在接收者receiver上的一个函数。接收者可以是任意类型的变量,int,bool,struct等,多用于struct,但是不能是接口类型不能是指针类型,但是可以是其他类型的指针。
也就是说,方法还是面向对象的方法,只不过不是作用在类上,而是作用在类型上,尤其作用在结构体上。简单理解也可以把方法看作是结构体的一个字段。
一个类型(比如一个结构体)是可以有多个方法的。
不同类型的方法是可以同名的。
实现一个改名的例子:

  1. package main
  2. import "fmt"
  3. type cat struct {
  4. name string //姓名
  5. age int //年龄
  6. sex bool //性别
  7. }
  8. func (c *cat) changename(name string) { //changename方法作用在cat这个结构体上,传入指针
  9. c.name = name
  10. }
  11. func main() {
  12. mycat := cat{
  13. name: "喵",
  14. age: 1,
  15. sex: true,
  16. }
  17. mycat.changename("汪") //传值改名
  18. fmt.Println(mycat.name) //汪
  19. }

9.2.1 多重继承

Go怎么利用结构体和方法实现多重继承呢?嵌套。
一个结构的两个字段都是结构体,这两个字段又分别有各自的方法,那么实例化第一个结构体,则同时拥有所有的方法。

  1. package main
  2. import "fmt"
  3. //顶结构体,内嵌cat和dog结构体
  4. type Both struct {
  5. c cat
  6. d dog
  7. }
  8. //猫结构体
  9. type cat struct {
  10. name string //姓名
  11. age int //年龄
  12. sex bool //性别
  13. }
  14. //猫改名的方法
  15. func (c *cat) changename(name string) {
  16. c.name = name
  17. }
  18. //狗结构体
  19. type dog struct {
  20. name string //姓名
  21. age int //年龄
  22. sex bool //性别
  23. }
  24. //狗改年龄的方法
  25. func (d *dog) changenage(age int) {
  26. d.age = age
  27. }
  28. func main() {
  29. a := Both{ //实例化顶结构体
  30. c: cat{
  31. name: "喵",
  32. age: 1,
  33. sex: true,
  34. },
  35. d: dog{
  36. name: "汪",
  37. age: 2,
  38. sex: false,
  39. },
  40. }
  41. a.c.changename("喵2") //改猫名
  42. a.d.changenage(3) //改狗年龄
  43. fmt.Println(a.c.name, a.d.age) //喵2 3
  44. }