這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。歡迎來到 [Golang 系列教程](https://studygolang.com/subject/2)的第 27 篇。Go 不支援繼承,但它支援組合(Composition)。組合一般定義為“合并在一起”。汽車就是一個關於組合的例子:一輛汽車由車輪、引擎和其他各種組件組合在一起。## 通過嵌套結構體進行組合在 Go 中,通過在結構體內嵌套結構體,可以實現組合。組合的典型例子就是部落格文章。每一個部落格的文章都有標題、內容和作者資訊。使用組合可以很好地表示它們。通過學習本教程後面的內容,我們會知道如何?組合。我們首先建立一個 `author` 結構體。```gopackage mainimport ( "fmt")type author struct { firstName string lastName string bio string}func (a author) fullName() string { return fmt.Sprintf("%s %s", a.firstName, a.lastName)}```在上面的程式碼片段中,我們建立了一個 `author` 結構體,`author` 的欄位有 `firstname`、`lastname` 和 `bio`。我們還添加了一個 `fullName()` 方法,其中 `author` 作為接收者類型,該方法返回了作者的全名。下一步我們建立 `post` 結構體。```gotype 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`。該欄位指定 `author` 組成了 `post` 結構體。現在 `post` 可以訪問 `author` 結構體的所有欄位和方法。我們同樣給 `post` 結構體添加了 `details()` 方法,用於列印標題、內容和作者的全名與簡介。一旦結構體內嵌套了一個結構體欄位,Go 可以使我們訪問其嵌套的欄位,好像這些欄位屬於外部結構體一樣。所以上面第 11 行的 `p.author.fullName()` 可以替換為 `p.fullName()`。於是,`details()` 方法可以重寫,如下所示:```gofunc (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` 結構體都已準備就緒,我們來建立一個部落格文章來完成這個程式。```gopackage mainimport ( "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()}```[在 playground 上運行](https://play.golang.org/p/sskWaTpJgr)在上面程式中,main 函數在第 31 行建立了一個 `author` 結構體變數。而在第 36 行,我們通過嵌套 `author1` 來建立一個 `post`。該程式輸出:```bashTitle: Inheritance in Go Content: Go supports composition instead of inheritance Author: Naveen Ramanathan Bio: Golang Enthusiast ```## 結構體切片的嵌套我們可以進一步處理這個樣本,使用部落格文章的切片來建立一個網站。:)我們首先定義 `website` 結構體。請在上述代碼裡的 main 函數中,添加下面的代碼,並運行它。```gotype website struct { []post}func (w website) contents() { fmt.Println("Contents of Website\n") for _, v := range w.posts { v.details() fmt.Println() }}```在你添加上述代碼後,當你運行程式時,編譯器將會報錯,如下所示:```bashmain.go:31:9: syntax error: unexpected [, expecting field name or embedded type ```這項錯誤指出了嵌套的結構體切片 `[]post`。錯誤的原因是結構體不能嵌套一個匿名切片。我們需要一個欄位名。所以我們來修複這個錯誤,讓編譯器順利通過。```gotype website struct { posts []post}```可以看到,我給文章的切片 `[]post` 添加了欄位名 `posts`。現在我們來修改主函數,為我們的新網站建立一些文章吧。修改後的完整代碼如下所示:```gopackage mainimport ( "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()}```[在 playground 中運行](https://play.golang.org/p/gKaa0RbeAE)在上面的主函數中,我們建立了一個作者 `author1`,以及三個文章 `post1`、`post2` 和 `post3`。我們最後通過嵌套三個文章,在第 62 行建立了網站 `w`,並在下一行顯示內容。程式會輸出:```bashContents of WebsiteTitle: Inheritance in Go Content: Go supports composition instead of inheritance Author: Naveen Ramanathan Bio: Golang EnthusiastTitle: Struct instead of Classes in Go Content: Go does not support classes but methods can be added to structs Author: Naveen Ramanathan Bio: Golang EnthusiastTitle: Concurrency Content: Go is a concurrent language and not a parallel one Author: Naveen Ramanathan Bio: Golang Enthusiast ```本教程到此結束。祝你愉快。**上一教程 - [結構體取代類](https://studygolang.com/articles/12630)****下一教程 - [多態](https://studygolang.com/articles/12681)**
via: https://golangbot.com/inheritance
作者:Nick Coghlan 譯者:Noluye 校對:polaris1119
本文由 GCTT 原創編譯,Go語言中文網 榮譽推出
本文由 GCTT 原創翻譯,Go語言中文網 首發。也想加入譯者行列,為開源做一些自己的貢獻嗎?歡迎加入 GCTT!
翻譯工作和譯文發表僅用於學習和交流目的,翻譯工作遵照 CC-BY-NC-SA 協議規定,如果我們的工作有侵犯到您的權益,請及時聯絡我們。
歡迎遵照 CC-BY-NC-SA 協議規定 轉載,敬請在本文中標註並保留原文/譯文連結和作者/譯者等資訊。
文章僅代表作者的知識和看法,如有不同觀點,請樓下排隊吐槽
1772 次點擊