Go不支持继承,但是它支持组合。组合的一般定义是“放在一起”。组合的一个例子是一辆汽车。汽车由车轮、发动机和各种其他部件组成。
通过嵌入结构进行组合
Go 中的组合可以通过将一种结构类型嵌入到另一种结构类型中来实现。
博客文章是写作的完美示例。每篇博客文章都有标题、内容和作者信息。这可以用组合来完美地表达。在本教程的后续步骤中,我们将了解这是如何完成的。
让我们首先创建author
结构体。
package mainimport ( "fmt"
)type author struct { firstName stringlastName stringbio string
}func (a author) fullName() string { return fmt.Sprintf("%s %s", a.firstName, a.lastName)
}
在上面的代码片段中,我们创建了一个author
包含 firstName
、lastName
和 bio
的结构体。同时我们还增加fullName
的方法,该方法返回作者的全名。
下一步是创建blogPost
结构。
type blogPost struct { title stringcontent stringauthor
}func (b blogPost) details() { fmt.Println("Title: ", b.title)fmt.Println("Content: ", b.content)fmt.Println("Author: ", b.author.fullName())fmt.Println("Bio: ", b.author.bio)
}
该blogPost
结构有字段title
, content
。它还具有嵌入的匿名字段author
。该字段表示blogPost
结构体由author
组成。
现在blogPost
struct 可以访问author
结构的所有字段和方法。我们还在结构中添加了打印作者的标题、内容、全名和简介的details()
方法。
每当一个结构体字段嵌入到另一个结构体字段中时,Go 都会为我们提供访问嵌入字段,就像它们是外部结构体的一部分一样。
这意味着p.author.fullName()
可以替换为p.fullName()
. 因此该details()
方法可以重写如下,
func (p blogPost) details() { fmt.Println("Title: ", p.title)fmt.Println("Content: ", p.content)fmt.Println("Author: ", p.fullName())fmt.Println("Bio: ", p.bio)
}
现在我们已经准备好了author
和blogPost
结构,让我们通过创建一篇博客文章来完成这个程序。
package mainimport ( "fmt"
)type author struct { firstName stringlastName stringbio string
}func (a author) fullName() string { return fmt.Sprintf("%s %s", a.firstName, a.lastName)
}type blogPost struct { title stringcontent stringauthor
}func (b blogPost) details() { fmt.Println("Title: ", b.title)fmt.Println("Content: ", b.content)fmt.Println("Author: ", b.fullName())fmt.Println("Bio: ", b.bio)
}func main() { author1 := author{"Naveen","Ramanathan","Golang Enthusiast",}blogPost1 := blogPost{"Inheritance in Go","Go supports composition instead of inheritance",author1,}blogPost1.details()
}
Run in playground
上面程序的主要功能是创建一个新作者和创建了一个新帖子。调用嵌入author
.的details()
方法
该程序打印,
Title: Inheritance in Go
Content: Go supports composition instead of inheritance
Author: Naveen Ramanathan
Bio: Golang Enthusiast
嵌入结构体切片
我们可以更进一步地使用这个示例,并使用一部分博客文章创建一个网站。
我们首先定义website
结构体。请在现有程序的main函数上方添加以下代码并运行。
type website struct { []blogPost
}
func (w website) contents() { fmt.Println("Contents of Website\n")for _, v := range w.blogPosts {v.details()fmt.Println()}
}
当你添加上面的代码后运行上面的程序时,编译器会报以下错误,
main.go:31:9: syntax error: unexpected [, expecting field name or embedded type
此错误指向 struct 的嵌入切片[]blogPost
。原因是无法匿名嵌入切片。需要字段名称。因此,让我们修复这个错误,让编译器满意。
type website struct { blogPosts []blogPost
}
我添加了blogPosts
一个 slice字段[]blogPosts
。
现在让我们修改主要功能并为我们的新网站创建一些帖子。
下面给出修改main函数后的完整程序:
package mainimport ( "fmt"
)type author struct { firstName stringlastName stringbio string
}func (a author) fullName() string { return fmt.Sprintf("%s %s", a.firstName, a.lastName)
}type blogPost struct { title stringcontent stringauthor
}func (p blogPost) details() { fmt.Println("Title: ", p.title)fmt.Println("Content: ", p.content)fmt.Println("Author: ", p.fullName())fmt.Println("Bio: ", p.bio)
}type website struct { blogPosts []blogPost
}func (w website) contents() { fmt.Println("Contents of Website\n")for _, v := range w.blogPosts {v.details()fmt.Println()}
}func main() { author1 := author{"Naveen","Ramanathan","Golang Enthusiast",}blogPost1 := blogPost{"Inheritance in Go","Go supports composition instead of inheritance",author1,}blogPost2 := blogPost{"Struct instead of Classes in Go","Go does not support classes but methods can be added to structs",author1,}blogPost3 := blogPost{"Concurrency","Go is a concurrent language and not a parallel one",author1,}w := website{blogPosts: []blogPost{blogPost1, blogPost2, blogPost3},}w.contents()
}
Run in playground
在上面的 main 函数中,我们创建了一个作者author1
和三个帖子post1
,post2
和post3
。最后创建了网站w
。
该程序将输出,
Contents 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
本教程到此结束。祝你有美好的一天。请留下您的反馈和意见。