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
结构。我们还添加了一个方法 fullName()
,author
为接收者类型,返回作者的全名。
下一步是创建 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
struct 可以访问 author
结构的所有字段和方法。我们还在 post
结构中添加了 details()
方法,用于输出作者的title,content,fullName 和 bio。
每当一个 struct 字段嵌入另一个 struct 字段时,Go 为我们提供了访问嵌入字段的选项,就好像它们是外部结构的一部分一样。这意味着 p.author.fullName()
在第 11 行号中可以用 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
嵌入结构切片
我们可以将这个例子更进一步拓展,用一小段博客文章创建一个网站:)。
让我们首先定义网站结构。请在现有程序的主要功能之上添加以下代码并运行它。
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
这个错误指向 structs []post 的嵌入切片。原因是不能匿名嵌入一个切片,而需要一个字段名。让我们修改这个错误,让编译器正常。
type website struct {
posts []post
}
我已经将字段名 posts 添加到 post []post 的切片中。
现在让我们修改主函数,并为我们的新网站创建一些文章。
修改 main 函数后的完整程序如下
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()
}
在上面的主函数中,我们创建了一个author author1
和三个 posts post1
, post2
和 post3
。最后我们在 63 行创建了网站 w
。通过嵌入这 3 篇文章并在下一行显示内容。
这个程序将输出
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