Go语言中文网,致力于每日分享编码、开源等知识,欢迎关注我,会有意想不到的收获!
![37d05ea3c85229e3f40bb19bdaf5552e.png](https://img-blog.csdnimg.cn/img_convert/37d05ea3c85229e3f40bb19bdaf5552e.png)
Go 不支持继承,但它支持组合(Composition)。组合一般定义为“合并在一起”。汽车就是一个关于组合的例子:一辆汽车由车轮、引擎和其他各种部件组合在一起。
通过嵌套结构体进行组合
在 Go 中,通过在结构体内嵌套结构体,可以实现组合。
组合的典型例子就是博客帖子。每一个博客的帖子都有标题、内容和作者信息。使用组合可以很好地表示它们。通过学习本教程后面的内容,我们会知道如何实现组合。
我们首先创建一个 author 结构体。
![3e5d011b1e9a61447eaff18dfd6c2b0b.png](https://img-blog.csdnimg.cn/img_convert/3e5d011b1e9a61447eaff18dfd6c2b0b.png)
在上面的代码片段中,我们创建了一个 author 结构体,author 的字段有 firstname、lastname 和 bio。我们还添加了一个 fullName() 方法,其中 author 作为接收者类型,该方法返回了作者的全名。
下一步我们创建 post 结构体。
![9f9d16b6e66357bc9bf3488c78380318.png](https://img-blog.csdnimg.cn/img_convert/9f9d16b6e66357bc9bf3488c78380318.png)
post 结构体的字段有 title 和 content。它还有一个嵌套的匿名字段 author。该字段指定 author 组成了 post 结构体。现在 post 可以访问 author 结构体的所有字段和方法。我们同样给 post 结构体添加了 details() 方法,用于打印标题、内容和作者的全名与简介。
一旦结构体内嵌套了一个结构体字段,Go 可以使我们访问其嵌套的字段,好像这些字段属于外部结构体一样。所以上面第 11 行的 p.author.fullName() 可以替换为 p.fullName()。于是,details() 方法可以重写,如下所示:
![698d8354b90308da233bff3da236ac40.png](https://img-blog.csdnimg.cn/img_convert/698d8354b90308da233bff3da236ac40.png)
现在,我们的 author 和 post 结构体都已准备就绪,我们来创建一个博客帖子来完成这个程序。
![33181b411cebc699f2e34d593081d906.png](https://img-blog.csdnimg.cn/img_convert/33181b411cebc699f2e34d593081d906.png)
在上面程序中,main 函数在第 31 行新建了一个 author 结构体变量。而在第 36 行,我们通过嵌套 author1 来创建一个 post。该程序输出:
![55c6a6e4a8bd65c7da610e88d5846180.png](https://img-blog.csdnimg.cn/img_convert/55c6a6e4a8bd65c7da610e88d5846180.png)
结构体切片的嵌套
我们可以进一步处理这个示例,使用博客帖子的切片来创建一个网站。
我们首先定义 website 结构体。请在上述代码里的 main 函数中,添加下面的代码,并运行它。
![0f3ef49e31b4f645a45c6a23524dd088.png](https://img-blog.csdnimg.cn/img_convert/0f3ef49e31b4f645a45c6a23524dd088.png)
在你添加上述代码后,当你运行程序时,编译器将会报错,如下所示:
main.go:31:9: syntax error: unexpected [, expecting field name or embedded type
这项错误指出了嵌套的结构体切片 []post。错误的原因是结构体不能嵌套一个匿名切片。我们需要一个字段名。所以我们来修复这个错误,让编译器顺利通过。
![e9648af3492747d0879409c8935fa760.png](https://img-blog.csdnimg.cn/img_convert/e9648af3492747d0879409c8935fa760.png)
可以看到,我给帖子的切片 []post 添加了字段名 posts。
现在我们来修改主函数,为我们的新网站创建一些帖子吧。
修改后的完整代码如下所示:
![b4b7f25c64828b15be8312f63e46bb9a.png](https://img-blog.csdnimg.cn/img_convert/b4b7f25c64828b15be8312f63e46bb9a.png)
在上面的主函数中,我们创建了一个作者 author1,以及三个帖子 post1、post2 和 post3。我们最后通过嵌套三个帖子,在第 62 行创建了网站 w,并在下一行显示内容。
程序会输出:
![93f637da48fe9133d05c41e8e937997d.png](https://img-blog.csdnimg.cn/img_convert/93f637da48fe9133d05c41e8e937997d.png)
本教程到此结束。祝你愉快。
上一教程 - 「GCTT 出品」Go 系列教程——26. 结构体取代类
下一教程 - 多态
历史文章:
「GCTT 出品」Go 系列教程——1. 介绍与安装
「GCTT 出品」Go 系列教程——2. Hello World
「GCTT 出品」Go 系列教程——3. 变量
「GCTT 出品」Go 系列教程——4. 类型
「GCTT 出品」Go 系列教程——5. 常量
「GCTT 出品」Go 系列教程——6. 函数(Function)
「GCTT 出品」Go 系列教程——7. 包
Go 系列教程——8. if-else 语句
「GCTT 出品」Go 系列教程——9. 循环
「GCTT 出品」Go 系列教程——10. switch 语句
「GCTT 出品」Go 系列教程——11. 数组和切片
「GCTT 出品」Go 系列教程——12. 可变参数函数
「GCTT 出品」Go 系列教程——13. Maps
「GCTT 出品」Go 系列教程——14. 字符串
「GCTT 出品」Go 系列教程——15. 指针
「GCTT 出品」Go 系列教程——16. 结构体,这一篇就够
「GCTT 出品」Go 系列教程——17. 超全的方法教程
「GCTT 出品」Go 系列教程——18. 接口(一)
「GCTT 出品」Go 系列教程——19. 接口(二)
「GCTT 出品」Go 系列教程——20. 并发入门
「GCTT 出品」Go 系列教程——21. Go 协程
「GCTT 出品」Go 系列教程——22. 信道(channel)
「GCTT 出品」Go 系列教程——23. 缓冲信道和工作池
「GCTT 出品」Go 系列教程——24. Select
「GCTT 出品」Go 系列教程——25. Mutex
「GCTT 出品」Go 系列教程——26. 结构体取代类