Golang面向对象编程-struct(结构体)

                                          作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

一.什么是面向对象编程

  面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)是一种计算机编程架构。OOP 的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组合而成。OOP 达到了软件工程的三个主要目标:重用性、灵活性和扩展性。为了实现整体运算,每个对象都能够接收信息、处理数据和向其它对象发送信息。

二.面向对象编程常用名词介绍

  面向对象程序设计中的概念主要包括:对象、类、数据抽象、继承、动态绑定、数据封装、多态性、消息传递。通过这些概念面向对象的思想得到了具体的体现。

1>.对象(Object)

  可以对其做事情的一些东西。一个对象有状态、行为和标识三种属性。

2>.类(class)

  一个共享相同结构和行为的对象的集合。类(Class)定义了一件事物的抽象特点。通常来说,类定义了事物的属性和它可以做到的(它的行为)。举例来说,“狗”这个类会包含狗的一切基础特征,例如它的孕育、毛皮颜色和吠叫的能力。类可以为程序提供模版和结构。一个类的方法和属性被称为“成员”。

3>.封装(encapsulation):

  第一层意思:将数据和操作捆绑在一起,创造出一个新的类型的过程。第二层意思:将接口与实现分离的过程。

4>.继承

  类之间的关系,在这种关系中,一个类共享了一个或多个其他类定义的结构和行为。继承描述了类之间的“是一种”关系。子类可以对基类的行为进行扩展、覆盖、重定义。

5>.组合

  既是类之间的关系也是对象之间的关系。在这种关系中一个对象或者类包含了其他的对象和类。组合描述了“有”关系。

6>.多态

  类型理论中的一个概念,一个名称可以表示很多不同类的对象,这些类和一个共同超类有关。因此,这个名称表示的任何对象可以以不同的方式响应一些共同的操作集合。

7>.动态绑定

  也称动态类型,指的是一个对象或者表达式的类型直到运行时才确定。通常由编译器插入特殊代码来实现。与之对立的是静态类型。

8>.静态绑定

  也称静态类型,指的是一个对象或者表达式的类型在编译时确定。

9>.消息传递

  指的是一个对象调用了另一个对象的方法(或者称为成员函数)。

10>.方法

  也称为成员函数,是指对象上的操作,作为类声明的一部分来定义。方法定义了可以对一个对象执行那些操作。

三.Golang中的对象

  在Go语言中,也和 C 或者Python等其他语言一样,我们可以声明(自定义)新的类型,作为其它类型的属性或字段的容器。在Python或是C中,我们称这种数据类型为class类型,而在golang中它也有一个中文名字,叫做结构体。

1.定义一个新的类型

  1. /*
  2. #!/usr/bin/env gorun
  3. @author :yinzhengjie
  4. Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
  5. EMAIL:y1053419035@qq.com
  6. */
  7.  
  8. package main
  9.  
  10. type Chairman struct { //其中“type...struct”表示定义数据类型的关键字,而Chairman则是我们定义类型的名字。
  11. Name string //这里面的所有元素都是Chairman的属性,Name表示我们定义的名字的意思。
  12. age int //这个顾名思义就知道是年龄喽,只不过我这里故意将首字母小写,但是你可别小瞧这个小写哟,以后我们在说它的功能。
  13. }

2.声明以及定义的类型

  1. /*
  2. #!/usr/bin/env gorun
  3. @author :yinzhengjie
  4. Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
  5. EMAIL:y1053419035@qq.com
  6. */
  7.  
  8. package main
  9.  
  10. import "fmt"
  11.  
  12. type Chairman struct { //其中“type...struct”表示定义数据类型的关键字,而Chairman则是我们定义类型的名字。
  13. Name string //这里面的所有元素都是Chairman的属性,Name表示我们定义的名字的意思。
  14. age int //这个顾名思义就知道是年龄喽,只不过我这里故意将首字母小写,但是你可别小瞧这个小写哟,以后我们在说它的功能。
  15. }
  16.  
  17. func main() {
  18. var Leader Chairman //声明结构体为自定义的Chairman;
  19. var DeputyCadres_1 *Chairman //声明结构体为自定义的Chairman指针;
  20. DeputyCadres_2 := new(Chairman) //用内置函数new进行了初始化&{ };
  21. fmt.Println(Leader) //默认初始化为零值;
  22. fmt.Println(DeputyCadres_1) //<nil> 未初始化;
  23. fmt.Println(DeputyCadres_2)
  24. fmt.Println(DeputyCadres_1 == nil)
  25. DeputyCadres_1 = new(Chairman) //这种先声明再初始化的方式和直接初始化效果相同。
  26. fmt.Println(DeputyCadres_1)
  27. fmt.Println(DeputyCadres_1 == nil)
  28. }
  29.  
  30. #以上代码执行结果如下:
  31. { 0}
  32. <nil>
  33. &{ 0}
  34. true
  35. &{ 0}
  36. false

3.初始化定义的类型

a>.先声明再赋值

  1. /*
  2. #!/usr/bin/env gorun
  3. @author :yinzhengjie
  4. Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
  5. EMAIL:y1053419035@qq.com
  6. */
  7.  
  8. package main
  9.  
  10. import "fmt"
  11.  
  12. type Chairman struct { //其中“type...struct”表示定义数据类型的关键字,而Chairman则是我们定义类型的名字。
  13. Name string //这里面的所有元素都是Chairman的属性,Name表示我们定义的名字的意思。
  14. age int //这个顾名思义就知道是年龄喽,只不过我这里故意将首字母小写,但是你可别小瞧这个小写哟,以后我们在说它的功能。
  15. }
  16.  
  17. func main() {
  18. var p Chairman
  19. p.Name = "习大大"
  20. p.age = 64
  21. fmt.Println(p)
  22. }
  23.  
  24. #以上代码执行结果如下:
  25. {习大大 64}

b>.按照位置初始化

  1. /*
  2. #!/usr/bin/env gorun
  3. @author :yinzhengjie
  4. Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
  5. EMAIL:y1053419035@qq.com
  6. */
  7.  
  8. package main
  9.  
  10. import "fmt"
  11.  
  12. type Chairman struct { //其中“type...struct”表示定义数据类型的关键字,而Chairman则是我们定义类型的名字。
  13. Name string //这里面的所有元素都是Chairman的属性,Name表示我们定义的名字的意思。
  14. age int //这个顾名思义就知道是年龄喽,只不过我这里故意将首字母小写,但是你可别小瞧这个小写哟,以后我们在说它的功能。
  15. }
  16.  
  17. func main() {
  18. var p Chairman
  19. p = Chairman{
  20. "习大大",
  21. 64,
  22. }
  23. fmt.Println(p)
  24. }
  25.  
  26. #以上代码执行结果如下:
  27. {习大大 64}

c>.按照key和value的方式初始化

  1. /*
  2. #!/usr/bin/env gorun
  3. @author :yinzhengjie
  4. Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
  5. EMAIL:y1053419035@qq.com
  6. */
  7.  
  8. package main
  9.  
  10. import "fmt"
  11.  
  12. type Chairman struct { //其中“type...struct”表示定义数据类型的关键字,而Chairman则是我们定义类型的名字。
  13. Name string //这里面的所有元素都是Chairman的属性,Name表示我们定义的名字的意思。
  14. age int //这个顾名思义就知道是年龄喽,只不过我这里故意将首字母小写,但是你可别小瞧这个小写哟,以后我们在说它的功能。
  15. }
  16.  
  17. func main() {
  18. var p Chairman
  19. p = Chairman{
  20. age:124,
  21. Name:"毛爷爷",
  22. }
  23. fmt.Println(p)
  24. }
  25.  
  26. #以上代码执行结果如下:
  27. {毛爷爷 124}

4.自定义struct案例及其用法案例展示

  1. /*
  2. #!/usr/bin/env gorun
  3. @author :yinzhengjie
  4. Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
  5. EMAIL:y1053419035@qq.com
  6. */
  7.  
  8. package main
  9. import "fmt"
  10.  
  11. type Student struct { // 声明一个新的类型叫Student
  12. name string
  13. age int
  14. }
  15.  
  16. func AgeConstrast(p1, p2 Student) (Student, int) { // 我们将定义的struct类型传递进来进行比较两个人的年龄,返回年龄大的那个人,并且返回年龄差
  17. if p1.age>p2.age { // 比较 p1 和p2这两个人的年龄
  18. return p1, p1.age-p2.age
  19. }
  20. return p2, p2.age-p1.age
  21. }
  22. func main() {
  23. var yinzhengjie Student
  24.  
  25. yinzhengjie.name, yinzhengjie.age = "尹正杰", 18 // 赋值初始化
  26.  
  27. bingan := Student{age:25, name:"饼干"} //按照key:value方式的初始化赋值
  28.  
  29. Leader:= Student{"习大大", 43} // 按照 struct定义顺序初始化值
  30. yzj_bg, tb_diff := AgeConstrast(yinzhengjie, bingan) //将我们赋值好的数据传入我们定义的函数中,然后用两个参数接受返回值。
  31. yzj_xdd, tp_diff := AgeConstrast(yinzhengjie, Leader)
  32. bg_xdd, bp_diff := AgeConstrast(bingan, Leader)
  33. fmt.Printf("当【·\033[31;1m%s\033[0m·】 和 【%s】 在一起时, 【%s】 比他大 【%d】 岁!\n",
  34. yinzhengjie.name, bingan.name, yzj_bg.name, tb_diff)
  35. fmt.Printf("当【·\033[31;1m%s\033[0m·】 和 【%s】 在一起时, 【%s】 比他大 【%d】 岁!\n",
  36. yinzhengjie.name, Leader.name, yzj_xdd.name, tp_diff)
  37. fmt.Printf("当【·\033[31;1m%s\033[0m·】 和 【%s】 在一起时, 【%s】 比他大 【%d】 岁!\n",
  38. bingan.name, Leader.name, bg_xdd.name, bp_diff)
  39. }
  40.  
  41. #以上代码执行结果如下:
  42. 当【·尹正杰·】 【饼干】 在一起时, 【饼干】 比他大 7 岁!
  43. 当【·尹正杰·】 【习大大】 在一起时, 【习大大】 比他大 25 岁!
  44. 当【·饼干·】 【习大大】 在一起时, 【习大大】 比他大 18 岁!

5.自定义struct案例及其用法案例展示

  1. /*
  2. #!/usr/bin/env gorun
  3. @author :yinzhengjie
  4. Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
  5. EMAIL:y1053419035@qq.com
  6. */
  7.  
  8. package main
  9.  
  10. import (
  11. "math"
  12. "fmt"
  13. )
  14.  
  15. type Point struct { //定义一个结构题体,你可以理解是是Python中的class
  16. X,Y float64
  17. }
  18.  
  19. func (p Point)Distence(q Point) float64 { //给p对象定义一个Distence的方法,你可以理解绑定了一个Distence的方法。
  20. return math.Hypot(q.X-p.X,q.Y-p.Y)
  21. }
  22.  
  23. func main() {
  24. p := Point{1,2}
  25. q := Point{4,6}
  26. fmt.Println((p.Distence(q))) //类的调用方式,注意,如果定义就要如何调用!(这里是调用p的Distence方法。)
  27. }
  28.  
  29. #以上代码输出结果如下:
  30. 5

6.花式玩法struct案例展示(纯中文编程)

  1. /*
  2. #!/usr/bin/env gorun
  3. @author :yinzhengjie
  4. Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
  5. EMAIL:y1053419035@qq.com
  6. */
  7.  
  8. package main
  9.  
  10. import "fmt"
  11.  
  12. type 车的属性 struct {
  13. 名称 string
  14. 描述 string
  15. 是否需要备用 bool
  16. }
  17.  
  18. type 车的特性 []车的属性 //“车的特性”类型是包含结构体“车的属性”类型的数组切片,你可以理解是起了一个别名。
  19.  
  20. func (零件 车的特性) 备件方法()(车的信息 车的特性) { //给“车的特性”绑定一个叫“备件”的方法起名为“零件”。
  21. for _,part := range 零件{
  22. if part.是否需要备用 { //只将有备胎的车追加到“车的信息”这个空切片中。
  23. 车的信息 = append(车的信息,part)
  24. }
  25. }
  26. return 车的信息
  27. }
  28.  
  29. type 汽车 struct { //“汽车”由“车身大小”组成
  30. 车身大小 string
  31. 车的特性 //没有给“车的特性”指定一个名称,我们是要保证实现“内嵌”。这样可以提供自动的委托,不需特殊的声明,
  32. // 例如“汽车.备件方法()”和“汽车.车的特性.备件方法()”是等同的。
  33. }
  34.  
  35. var (
  36. 特斯拉 = 车的特性{
  37. {"Tesla_90D(加速时间)", "100km/2.9s", true},
  38. {"车身大小", "109.47万元", false},
  39. {"颜色", "red", false},
  40. }
  41.  
  42. 宝马 = 车的特性{
  43. {"BMW M4敞篷轿跑车(加速时间)", "100km/4.4s", true},
  44. {"价格", "1,098,000美元", true},
  45. {"倍耐力轮胎", "兰博基尼Huracan LP580-2前轮原配", true},
  46. {"夏季冰丝汽车坐垫", "1088.00", true},
  47. }
  48.  
  49. 兰博基尼 = 车的特性{
  50. {"Avetador(加速时间)", "100km/2.8s", true},
  51. {"价格", "648.80-801.15万", true},
  52. {"颜色", "黑色", false},
  53. {"夏季冰丝汽车坐垫", "1088.00", true},
  54. }
  55. )
  56.  
  57. func main() {
  58. roadBike := 汽车{车身大小: "5037×2070×mm", 车的特性: 特斯拉}
  59. mountainBike := 汽车{车身大小: "1678*1870*1398", 车的特性: 宝马}
  60. recumbentBike := 汽车{车身大小: "4780*2030*1136", 车的特性: 兰博基尼}
  61. fmt.Println(roadBike.备件方法())
  62. fmt.Println(mountainBike.备件方法())
  63. fmt.Println(recumbentBike.备件方法())
  64. comboParts := 车的特性{}
  65. comboParts = append(comboParts, mountainBike.车的特性...)
  66. comboParts = append(comboParts, roadBike.车的特性...)
  67. comboParts = append(comboParts, recumbentBike.车的特性...)
  68.  
  69. fmt.Println(len(comboParts), comboParts[9:])
  70. fmt.Println(comboParts.备件方法())
  71. }
  72.  
  73. #以上代码执行结果如下:
  74. [{Tesla_90D(加速时间) 100km/2.9s true}]
  75. [{BMW M4敞篷轿跑车(加速时间) 100km/4.4s true} {价格 1,098,000美元 true} {倍耐力轮胎 兰博基尼Huracan LP580-2前轮原配 true} {夏季冰丝汽车坐垫 1088.00 true}]
  76. [{Avetador(加速时间) 100km/2.8s true} {价格 648.80-801.15 true} {夏季冰丝汽车坐垫 1088.00 true}]
  77. 11 [{颜色 黑色 false} {夏季冰丝汽车坐垫 1088.00 true}]
  78. [{BMW M4敞篷轿跑车(加速时间) 100km/4.4s true} {价格 1,098,000美元 true} {倍耐力轮胎 兰博基尼Huracan LP580-2前轮原配 true} {夏季冰丝汽车坐垫 1088.00 true} {Tesla_90D(加速时间) 100km/2.9s true} {Avetador(加速时间) 100km/2.8s true} {价格 648.80-801.15 true} {夏季冰丝汽车坐垫 1088.00 true}]

四.Golang中的匿名字段

  结构体里的字段可以只有类型名,而没有字段名,这种字段称为匿名字段。匿名字段可以是一个结构体、切片等复合类型,也可以是 int 这样的简单类型。但建议不要把简单类型作为匿名字段。golang中每种类型只能有一个匿名域。可以用来实现oop中的继承。

1.匿名字段的初始化操作

  1. /*
  2. #!/usr/bin/env gorun
  3. @author :yinzhengjie
  4. Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
  5. EMAIL:y1053419035@qq.com
  6. */
  7.  
  8. package main
  9. import "fmt"
  10. type Student struct {
  11. name string //第一个参数“name”叫做字段名称,第二个参数“string”叫做字段类型。
  12. age int
  13. speciality string
  14. int //我们知道“int”是内置的数据类型,我们可以在前面加一个字段名称,如果不加就是用内置类型作为匿名字段。
  15. }
  16. type Classroom struct {
  17. Student // 这是我们自定义的结构体,我们可以在其前面加一个字段名称,如果不加的话就是匿名字段,那么默认 Classroom就包含了Student 的所有字段。
  18. area int
  19. name string
  20. }
  21. func main() {
  22. yinzhengjie := Classroom{ //我们给“Classroom”这个结构体定义了三个属性,一个是“Student”匿名字段,一个是“area”,还有一个是“name”。以下是赋值操作。
  23. Student{
  24. name:"尹正杰",
  25. age:18,
  26. speciality:"Basketball",
  27. int:175,
  28. },
  29. 100 ,
  30. "Golang进阶之路",
  31. }
  32. fmt.Println(yinzhengjie)
  33. }
  34.  
  35. #以上代码执行结果如下:
  36. {{尹正杰 18 Basketball 175} 100 Golang进阶之路}

2.匿名字段的查询操作

  1. /*
  2. #!/usr/bin/env gorun
  3. @author :yinzhengjie
  4. Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
  5. EMAIL:y1053419035@qq.com
  6. */
  7.  
  8. package main
  9. import "fmt"
  10. type Student struct {
  11. Name string //第一个参数“name”叫做字段名称,第二个参数“string”叫做字段类型。
  12. Age int
  13. Speciality string
  14. int //我们知道“int”是内置的数据类型,我们可以在前面加一个字段名称,如果不加就是用内置类型作为匿名字段。
  15. }
  16. type Classroom struct {
  17. Student // 这是我们自定义的结构体,我们可以在其前面加一个字段名称,如果不加的话就是匿名字段,那么默认 Classroom就包含了Student 的所有字段。
  18. area int
  19. name string
  20. }
  21.  
  22. func MyEcho(p Classroom) { //该函数用来定义查看结构体信息的。
  23. fmt.Printf("学生的姓名是:【%v】\n",p.Student.Name)
  24. fmt.Printf("学生的身高是:【%d】\n",p.Student.int)
  25. fmt.Printf("学生的爱好是:【%s】\n",p.Student.Speciality)
  26. fmt.Printf("学生的身高是:【%d】\n",p.Student.int)
  27. fmt.Printf("教室的面积是:【%v】\n",p.area)
  28. fmt.Printf("教室的名称是:【%s】\n",p.name)
  29.  
  30. }
  31. func main() {
  32. yinzhengjie := Classroom{ //我们给“Classroom”这个结构体定义了三个属性,一个是“Student”匿名字段,一个是“area”,还有一个是“name”。以下是赋值操作。
  33. Student{
  34. Name:"尹正杰",
  35. Age:18,
  36. Speciality:"Basketball",
  37. int:175,
  38. },
  39. 130 ,
  40. "Golang进阶之路",
  41. }
  42. MyEcho(yinzhengjie)
  43. }
  44.  
  45. #以上代码执行结果如下:
  46. 学生的姓名是:【尹正杰】
  47. 学生的身高是:【175
  48. 学生的爱好是:【Basketball
  49. 学生的身高是:【175
  50. 教室的面积是:【130
  51. 教室的名称是:【Golang进阶之路】

3.匿名字段的修改

  1. /*
  2. #!/usr/bin/env gorun
  3. @author :yinzhengjie
  4. Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
  5. EMAIL:y1053419035@qq.com
  6. */
  7.  
  8. package main
  9. import "fmt"
  10. type Student struct {
  11. Name string //第一个参数“name”叫做字段名称,第二个参数“string”叫做字段类型。
  12. Age int
  13. Speciality string
  14. int //我们知道“int”是内置的数据类型,我们可以在前面加一个字段名称,如果不加就是用内置类型作为匿名字段。
  15. }
  16. type Classroom struct {
  17. Student // 这是我们自定义的结构体,我们可以在其前面加一个字段名称,如果不加的话就是匿名字段,那么默认 Classroom就包含了Student 的所有字段。
  18. area int
  19. name string
  20. }
  21.  
  22. func MyEcho(p Classroom) { //该函数用来定义查看结构体信息的。
  23. fmt.Printf("学生的姓名是:【%v】\n",p.Student.Name)
  24. fmt.Printf("学生的身高是:【%d】\n",p.Student.int)
  25. fmt.Printf("学生的爱好是:【%s】\n",p.Student.Speciality)
  26. fmt.Printf("学生的身高是:【%d】\n",p.Student.int)
  27. fmt.Printf("教室的面积是:【%v】\n",p.area)
  28. fmt.Printf("教室的名称是:【%s】\n",p.name)
  29.  
  30. }
  31. func main() {
  32. yinzhengjie := Classroom{ //我们给“Classroom”这个结构体定义了三个属性,一个是“Student”匿名字段,一个是“area”,还有一个是“name”。以下是赋值操作。
  33. Student{
  34. Name:"尹正杰",
  35. Age:18,
  36. Speciality:"Basketball",
  37. int:175,
  38. },
  39. 130 ,
  40. "Golang进阶之路",
  41. }
  42. yinzhengjie.Student.Name = "yinzhengjie" //此处我们修改了“Classroom”的匿名字段“Student”的“Name”属性。
  43. yinzhengjie.name = "Golang自动化运维工具" //这里我们修改了“Classroom”的“name”属性。
  44. MyEcho(yinzhengjie)
  45. }
  46.  
  47. #以上代码执行结果如下:
  48. 学生的姓名是:【yinzhengjie
  49. 学生的身高是:【175
  50. 学生的爱好是:【Basketball
  51. 学生的身高是:【175
  52. 教室的面积是:【130
  53. 教室的名称是:【Golang自动化运维工具】

五.面向对象之method(方法)

  好了,现在我们已经学会了struct的基本知识结合之前学习函数的知识。现在假设有这么一个场景,你定义了一个 struct 叫做长方形,你现在想要计算他的面积,那么按照我们以往的的思路应该会用下面的方式来实现:

  1. /*
  2. #!/usr/bin/env gorun
  3. @author :yinzhengjie
  4. Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
  5. EMAIL:y1053419035@qq.com
  6. */
  7.  
  8. package main
  9.  
  10. import "fmt"
  11.  
  12. const PI = 3.14 //定义pi的大小。
  13.  
  14. type Square struct { //定义一个长方形的类型
  15. length,width float64
  16. }
  17. type Trapezoid struct { //定义一个梯形
  18. UpperLength float64
  19. BelowLength float64
  20. Height float64
  21. waist float64
  22. }
  23. type Circle struct {
  24. radius float64
  25. }
  26.  
  27. func SquareArea(a Square) float64 {
  28. return a.length * a.width
  29. }
  30.  
  31. func TrapezoidArea(a Trapezoid)float64 {
  32. return (a.UpperLength + a.BelowLength)*a.Height/2
  33. }
  34.  
  35. func CircleArea(a Circle) float64 {
  36. return PI*a.radius*a.radius
  37. }
  38.  
  39. func SquarePerimeter(a Square)float64 {
  40. return (a.width + a.length)*2
  41. }
  42.  
  43. func TrapezoidPerimeter (a Trapezoid)float64 {
  44. return a.UpperLength + a.BelowLength + a.waist*2
  45. }
  46.  
  47. func CirclePerimeter(a Circle) float64 {
  48. return 2*PI*a.radius
  49. }
  50.  
  51. func main() {
  52. a := Square{10,20}
  53. fmt.Printf("正方形的面积是【%v】\n",SquareArea(a))
  54. fmt.Printf("正方形的周长是【%v】\n",SquarePerimeter(a))
  55. b := Trapezoid{10,20,5,15}
  56. fmt.Printf("梯形的面积是【%v】\n",TrapezoidArea(b))
  57. fmt.Printf("梯形的周长是【%v】\n",TrapezoidPerimeter(b))
  58. c := Circle{5}
  59. fmt.Printf("圆形的面积是【%v】\n",CircleArea(c))
  60. fmt.Printf("圆形的周长是【%v】\n",CirclePerimeter(c))
  61. }

1.初探method(方法)

  以上的方法的确可以实现我们想要的功能,但是每实现一个功能都得新写一个函数,需要重新给它起个名字。那如果让我们求五边形,六边形,多边形等等,就得写多个函数去实现。但是仔细看下以上的代码,其实就是实现了求面积和求周长的功能,如果我们可以将面积和周长分一个类,返回把正方形和梯形等求面积的都同意用一个Area方法去接受岂不更好,也不需要我们没次实现一个功能都得去写一个函数名。今天我们就讲解一下函数的另一种形态,带有接收者的函数,我们称为 method。因此,我们可以把上面的代码修改后一下

  1. /*
  2. #!/usr/bin/env gorun
  3. @author :yinzhengjie
  4. Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
  5. EMAIL:y1053419035@qq.com
  6. */
  7.  
  8. package main
  9.  
  10. import "fmt"
  11.  
  12. const PI = 3.14 //定义pi的大小。
  13.  
  14. type Square struct { //定义一个长方形的类型
  15. length,width float64
  16. }
  17. type Trapezoid struct { //定义一个梯形
  18. UpperLength float64
  19. BelowLength float64
  20. Height float64
  21. waist float64
  22. }
  23. type Circle struct {
  24. radius float64
  25. }
  26.  
  27. func (a Square)Area()float64 { //我们可以给正方形设置求面积的(method)方法。
  28. return a.width * a.length
  29. }
  30. func (a Trapezoid) Area() float64 { //我们可以给梯形设置求面积的方法。
  31. return (a.UpperLength + a.BelowLength)*a.Height/2
  32. }
  33.  
  34. func (a Circle) Area() float64{ //我们圆形给正方形设置求面积的方法。
  35. return PI*a.radius*a.radius
  36. }
  37.  
  38. func (a Square)Perimeter()float64 { //我们可以给正方形设置求周长的方法。
  39. return (a.width + a.length)*2
  40. }
  41.  
  42. func (a Trapezoid)Perimeter()float64 {
  43. return a.UpperLength + a.BelowLength + a.waist*2
  44. }
  45.  
  46. func (a Circle)Perimeter()float64 {
  47. return 2*PI*a.radius
  48. }
  49.  
  50. func main() {
  51. a := Square{10,20}
  52. fmt.Printf("正方形的面积是【%v】\n",a.Area()) //注意其调用方式。
  53. fmt.Printf("正方形的周长是【%v】\n",a.Perimeter())
  54. b := Trapezoid{10,20,5,15}
  55. fmt.Printf("梯形的面积是【%v】\n",b.Area())
  56. fmt.Printf("梯形的周长是【%v】\n",b.Perimeter())
  57. c := Circle{5}
  58. fmt.Printf("圆形的面积是【%v】\n",c.Area())
  59. fmt.Printf("圆形的周长是【%v】\n",c.Perimeter())
  60. }

2.指针接受者

  1. /*
  2. #!/usr/bin/env gorun
  3. @author :yinzhengjie
  4. Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
  5. EMAIL:y1053419035@qq.com
  6. */
  7.  
  8. package main
  9.  
  10. import (
  11. "fmt"
  12. )
  13.  
  14. type Point struct {
  15. X,Y float64
  16. }
  17.  
  18. func (p *Point) ScaleBy(factor float64) { //想要修改p的值就得传指针类型"*Point",注意,如果这里传递不是指针的话讲无法对其属性进行更改!
  19. p.X *= factor // 等价于:X = X * factor,对对象P进行操作,修改其私有属性。
  20. p.Y *= factor
  21. }
  22.  
  23. func main() {
  24. //两种调用方式:
  25. p := Point{100,200}
  26. p.ScaleBy(2) //姿势一:直接调用
  27. fmt.Println(p)
  28.  
  29. p1 := Point{100,200} //姿势二:声明结构体后再用指针指向
  30. p2 :=&p1 //使用结构体调用,再取其内存地址
  31. p2.ScaleBy(2)
  32. fmt.Println(p2)
  33. }
  34.  
  35. #以上代码执行结果如下:
  36. {200 400}
  37. &{200 400}

Golang面向对象编程-struct(结构体)的更多相关文章

  1. Golang的面向对象编程【结构体、方法、继承、接口】

    Golang也支持面向对象编程.但与以前学过传统的面向对象编程语言有区别.1)Golang没有类class,Go语言的结构体struct和类class有相似的特性.2)Golang中不存在继承,方法重 ...

  2. golang 面向对象编程

    概述 Golang语言的面向对象与c++,py等语言有所不同,是由于Golang不支持继承:与上述支持聚合和继承的面向对象的语言不同,Golang只支持聚合(也叫做组合)和嵌入.聚合和嵌入的区别: t ...

  3. 3.11 Go Struct结构体

    3.11 Go Struct结构体 Golang支持OOP面向对象编程. Go的结构体struct如同python的class. Go基于struct实现OOP特性,只有组合composition这个 ...

  4. C# Struct结构体里数组长度的指定

    typedef struct Point{ unsigned short x; unsigned short y; }mPoint;//点坐标 typedef struct Line{ mPoint ...

  5. C语言 Struct 结构体在 Java 中的体现

    大一整个学期完成了 C 语言的学习,大二就进入了Java 的学习. 和C语言一样,我们都会尝试写一个小小的学生管理系统什么的,学习过 C 语言同学知道,在管理系统中 Struct 结构体是个很好用的东 ...

  6. go struct结构体

    struct结构体 用来自定义复杂数据结构 struct里面可以包含多个字段(属性),字段可以是任意类型 struct类型可以定义方法,注意和函数的区分 struct类型是值类型 struct类型可以 ...

  7. struct结构体在c和c++中的差别

    非常多次遇到这个struct的问题,今天在这里简单总结一下我的理解 一.struct在C 中的使用 1.单独使用struct定义结构体类型 struct Student { int id; int n ...

  8. Golang通过反射获取结构体的标签

    Golang通过反射获取结构体的标签 例子: package main import ( "fmt" "reflect" ) type resume struc ...

  9. C#基础--struct(结构体)

    结构体和类有点类似    我们定义一个类的时候    是class   类名   定义结构体的时候是 struct   结构体名 结构体的写法 struct Point { // public int ...

随机推荐

  1. Python学习笔记(一)——初学Python

    1.Python环境配置 本人配置Python2.7及Python3.6版本 将Python3.6环境配置在线,因此默认为Python3.6版本 Python2.7及Python3.6共存 2.简单操 ...

  2. K 班前7次作业成绩汇总

    K 班前7次作业成绩汇总 得分榜 千帆竞发 详细 短学号 名 1 2 3 4 5 6 7 TOTAL 505 基智 4.55 1 -2 0 0 -10 4.37 -2.08 414 圳源 5.43 2 ...

  3. IO学习

    ---恢复内容开始--- 命名规则: 1.类名使用 UpperCamelCase 风格,必须遵从驼峰形式,但以下情形例外:(领域模型 的相关命名)DO / BO / DTO / VO 等. 2.方法名 ...

  4. OSI的七层模型介绍

    应用层: 文件传输,电子邮件,文件服务,虚拟终端 TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 表示层: 数据格式化,代码转换,数据加密 没有协议. (信息的语法语义以及它们的 ...

  5. [linux学习]sysctl 以及 net.ipv4.ip_forward

    1. sysctl 命令显示 当前系统的参数配置信息 显示全部配置信息 sysctl -a 帮助信息主要如下: [root@k8s-master ~]# sysctl -help Usage: sys ...

  6. socketserver及相关的类 (处理socket服务端)+ event事件的使用

    编写简单的套接字服务器并不难,然而,如果要创建的并非简单服务器,还要求助于服务器模块. 模块SocketServer是标准库提供的服务器框架的基石,这个框架包括好多服务器,他们基本服务器的基础上添加了 ...

  7. 数字证书签发,授权等相关以及https建立通信过程

    一直以来都对数字证书的签发,以及信任等事情一知半解.总算有个闲适的周末来总结和深入一下相关的知识. CA: CA(Certificate Authority)是证书的签发机构,它是负责管理和签发证书的 ...

  8. matplotlib之随机漫步

    # 随机漫步类 from random import choice from matplotlib import pyplot as plt from pylab import mpl from ma ...

  9. AXI4

    axis  AXI4-stream 去掉了地址项,允许无限制的数据突发传输规模: 摘自http://xilinx.eetrend.com/blog/11443

  10. ImportError: cannot import name descriptor_pb2

    重新编译protobuf 下载地址:https://github.com/google/protobuf $cd /path/protobuf/python $python setup.py buil ...