package main import "fmt" // Human 定义一个名为Human的结构体 type Human struct { Name string // 姓名 Age int // 年龄 Sex string // 性别 } // Intro Human结构体的自我介绍方法 func (h *Human) Intro() { fmt.Printf("俺叫%v(%v),今年%v岁。\n", (*h).Name, (*h).Sex, (*h).Age) } // Programmer 定义一个名为Programmer的结构体,该结构体将嵌入Human结构体 type Programmer struct { Human // 嵌入Human结构体,此时Programmer结构体就能获得了Human结构体的所有字段和方法 Language string // 所使用的编程语言 WorkYears float64 // 工作年限 } // Intro Programmer结构体的自我介绍方法 // 重要说明:Go语言只有组合,该方法不会覆盖Human的同名方法,所以Programmer既有自己的Intro()方法,同时也有Human的Intro()方法, // 不要用面向对象的思维来理解这段代码,在Go语言里这叫做方法提升,在main()函数里会演示如何分别调用两个Intro()方法。 func (p *Programmer) Intro() { fmt.Printf( "俺叫%v(%v),今年%v岁,职业是%v程序猿,工作年限%v年。\n", (*p).Name, (*p).Sex, (*p).Age, (*p).Language, (*p).WorkYears, ) } func main() { programmer := new(Programmer) (*programmer).Name = "张三" (*programmer).Age = 18 (*programmer).Sex = "男" (*programmer).Language = "PHP" (*programmer).WorkYears = 3.14 // 调用Programmer自身的Intro()方法 (*programmer).Intro() // 俺叫张三(男),今年18岁,职业是PHP程序猿,工作年限3.14年。 // 调用Human的Intro()方法 (*programmer).Human.Intro() // 俺叫张三(男),今年18岁。 }
package main import ( "fmt" "time" ) type MyTime struct { time.Time // 嵌入标准库的time包的Time结构体 } func (mt *MyTime) Location() string { return "Asia/Shanghai" } func main() { mt := &MyTime{} // 调用自身的Location()方法 fmt.Printf("mt.Location() is %+v \n", mt.Location()) // mt.Location() is Asia/Shanghai // 调用time.Time的Location()方法 fmt.Printf("mt.Time.Location() is %+v \n", mt.Time.Location()) // mt.Time.Location() is UTC }
package main import "fmt" type People struct{} func (p *People) ShowA() { fmt.Println("People.ShowA()") p.ShowB() } func (p *People) ShowB() { fmt.Println("People.ShowB()") } type Teacher struct { People // Teacher嵌入了People,所以Teacher获得了People的全部字段和方法 } // ShowB 重要说明:Teacher.ShowB()没有覆盖People.ShowB()。 func (t *Teacher) ShowB() { fmt.Println("Teacher.ShowB()") } func main() { t := Teacher{} t.ShowA() // ========== 输出结果 ========== // // People.ShowA() // People.ShowB() } // ========== 说明 ========== // // 1、上面的代码对于使用面向对象语言的开发者可能无法理解,其实只要记住一件事,那么一切都会变得非常容易理解, // 那就是Go语言只有组合,没有继承,既然没有继承那就不存在方法覆盖,即Teacher.ShowB()没有覆盖People.ShowB()。 // 2、这里也可以从另一个角度来理解,那就是Go语言里没有隐式转换,既然ShowA()方法声明了p的数据类型是*People, // 那么p就肯定是*People类型变量,其中不可能发生隐式转换,从而p.ShowB()肯定是调用People.ShowB()方法。
package main import "fmt" type Human struct { Name string // 姓名 Birth int // 出生 Sex string // 性别 } func (h *Human) Intro() { fmt.Printf("俺叫%v(%v),出生于%v年。\n", (*h).Name, (*h).Sex, (*h).Birth) } type Teacher struct { Human // 匿名嵌入Human结构体 } type Programmer struct { Human Human // 具名嵌入Human结构体(并且是同名) } func main() { teacher := &Teacher{} programmer := &Programmer{} // 【推荐写法】 (*teacher).Name = "张三" (*teacher).Birth = 2003 (*teacher).Sex = "男" (*teacher).Intro() // 俺叫张三(男),出生于2003年。 // 【不推荐写法】 // 不推荐原因:Human是被匿名嵌入Teacher,如果加上“.Human”容易误解是被具名嵌入 (*teacher).Human.Name = "李四" (*teacher).Human.Birth = 2004 (*teacher).Human.Sex = "女" (*teacher).Human.Intro() // 俺叫李四(女),出生于2004年。 // 具名嵌入只有一种写法,不存在推不推荐 (*programmer).Human.Name = "王五" (*programmer).Human.Birth = 2005 (*programmer).Human.Sex = "男" (*programmer).Human.Intro() // 俺叫王五(男),出生于2005年。 } // ========== 说明 ========== // // 1、一般来说嵌入结构体使用匿名的方式即可,除非有特殊需求才使用具名嵌入。
Copyright © 2024 码农人生. All Rights Reserved