歡迎繼續Golang系列教程第27節
Go並不支持繼承,但是它支持組合。組合的通用定義是 “放到一起”。組合的一個例子是 汽車,汽車由車輪,引擎和各種其他部件組成。
通過嵌入結構體組合
在 Go 中,組合可以通過將一個結構體類型嵌入另一個來獲得。
博客文章是組合的一個完美例子。每個博客文章都有一個標題,內容和作者信息。這可以通過使用組合完美地表示。在文章的下一步,我們將學習這些是如何完成的。
我們首先創建 author
結構體。
package main
import (
"fmt"
)
type author struct {
firstName string
lastName string
bio string
}
func (a author) fullName() string {
return fmt.Sprintf("%s %s", a.firstName, a.lastName)
}
在上面的代碼片段,我們創建一個有 firstname
,lastName
和 bio
字段的結構體 author
。我們也使用 author
作爲接收器類型添加一個方法 fullName()
,該方法返回一個作者的全名字。
下一步將創建一個 post
結構體。
type post struct {
title string
content string
author
}
func (p post) details() {
fmt.Println("Title: ", p.title)
fmt.Println("Content: ", p.content)
fmt.Println("Author: ", p.author.fullName())
fmt.Println("Bio: ", p.author.bio)
}
post 結構體有字段 title
,content
。它還有一個嵌入的匿名字段 author
。這個字段表示 post
結構體由 author
組合而成。現在 post
結構體可以訪問 author
結構體的所有字段和方法。我們還爲 post
結構體添加 details()
方法,它將打印標題,內容和作者的命名和個人簡歷。
當一個結構體字段嵌入的是另一個結構體,Go 給我們提供了訪問嵌入字段的選項,就好比他們是外部結構體的一部分一樣。這意味着上面代碼第 11 行的 p.author.fullName()
可以使用 p.fullName()
代替。因此 details()
方法可以像下面一樣重寫。
func (p post) details() {
fmt.Println("Title: ", p.title)
fmt.Println("Content: ", p.content)
fmt.Println("Author: ", p.fullName())
fmt.Println("Bio: ", p.bio)
}
現在我們已經準備了 author
和 post
結構體。我們創建一個博客文章來完成這個程序
package main
import (
"fmt"
)
type author struct {
firstName string
lastName string
bio string
}
func (a author) fullName() string {
return fmt.Sprintf("%s %s", a.firstName, a.lastName)
}
type post struct {
title string
content string
author
}
func (p post) details() {
fmt.Println("Title: ", p.title)
fmt.Println("Content: ", p.content)
fmt.Println("Author: ", p.fullName())
fmt.Println("Bio: ", p.bio)
}
func main() {
author1 := author{
"Naveen",
"Ramanathan",
"Golang Enthusiast",
}
post1 := post{
"Inheritance in Go",
"Go supports composition instead of inheritance",
author1,
}
post1.details()
}
上面程序的主函數在第 31 行創建一個新的作者。在第 36 行通過嵌入 author1
創建一個新的博客文章 。這個程序打印
Title: Inheritance in Go
Content: Go supports composition instead of inheritance
Author: Naveen Ramanathan
Bio: Golang Enthusiast
嵌入結構體切片
我們要以繼續這個例子,使用博客文章切片 創建一個 web 站點。
我們首先定義 website
結構體。在上面已有的程序主函數添加下列代碼並運行它。
type website struct {
[]post
}
func (w website) contents() {
fmt.Println("Contents of Website\n")
for _, v := range w.posts {
v.details()
fmt.Println()
}
}
當在添加完上面代碼後運行程序,編譯器將報如下錯誤:
main.go:31:9: syntax error: unexpected [, expecting field name or embedded type
這個錯誤指向嵌入的結構體切片 []post
。原因是不能匿名嵌入一個切片。需要一個字段名。所以我們來修復該錯誤
type website struct {
posts []post
}
向 post 切片 []post
添加字段名 posts
。
現在修改主函數,爲 website 創建一個一些貼子。
修改完主函數後的完整程序提供如下
package main
import (
"fmt"
)
type author struct {
firstName string
lastName string
bio string
}
func (a author) fullName() string {
return fmt.Sprintf("%s %s", a.firstName, a.lastName)
}
type post struct {
title string
content string
author
}
func (p post) details() {
fmt.Println("Title: ", p.title)
fmt.Println("Content: ", p.content)
fmt.Println("Author: ", p.fullName())
fmt.Println("Bio: ", p.bio)
}
type website struct {
posts []post
}
func (w website) contents() {
fmt.Println("Contents of Website\n")
for _, v := range w.posts {
v.details()
fmt.Println()
}
}
func main() {
author1 := author{
"Naveen",
"Ramanathan",
"Golang Enthusiast",
}
post1 := post{
"Inheritance in Go",
"Go supports composition instead of inheritance",
author1,
}
post2 := post{
"Struct instead of Classes in Go",
"Go does not support classes but methods can be added to structs",
author1,
}
post3 := post{
"Concurrency",
"Go is a concurrent language and not a parallel one",
author1,
}
w := website{
posts: []post{post1, post2, post3},
}
w.contents()
}
在上面的主函數中,我們創建一個作者 author1
和三個貼子 post1
,post2
和 post3
。最後我們在第 62 行通過嵌入這三個貼子創建一個站點 w
,在下一行打印內容。
程序將輸出
Contents of Website
Title: Inheritance in Go
Content: Go supports composition instead of inheritance
Author: Naveen Ramanathan
Bio: Golang Enthusiast
Title: Struct instead of Classes in Go
Content: Go does not support classes but methods can be added to structs
Author: Naveen Ramanathan
Bio: Golang Enthusiast
Title: Concurrency
Content: Go is a concurrent language and not a parallel one
Author: Naveen Ramanathan
Bio: Golang Enthusiast
**下一教程 - 多態 **