欢迎继续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
**下一教程 - 多态 **