[一个有趣的bug] golang 组件化编程

loop_0 · · 1029 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

# [一个有趣的bug] golang 组件化编程 ## 组建化简述 * 众所周知, golang以组件化代替继承,这种组件化的思想有些类似于cpp的多继承(ps: 比多继承要好理解的多, 读者大可放心), 而多继承呢就会有一些经典的问题, 重定义和菱形继承, golang的组件化也存在这样类似的问题, 本文就该问题进行探讨。 * 重定义: cpp中的多继承,当类继承的两个父类包含名称相同的方法或属性, 则触发重定义, go语言中也存在相同的问题 ```go type Cat struct { } func (c *Cat)Eat(){ } type Dog struct{ } func (d *Dog)Eat(){ } type CatDog struct { Dog Cat } func test(){ cd := new(CatDog) //cd.Eat() //编译器无法确定调用的是Cat还是Dog的Eat() //需要明确指出 cd.Dog.Eat() cd.Cat.Eat() } ``` 不过组件化还是和继承完全不一样的如下代码 ```go type Cat struct { } func (c *Cat)Eat(){ fmt.Println("cat eat") } type Dog struct{ } func (d *Dog)Eat(){ fmt.Println("dog eat") } type ErHa struct { Dog } type CatDog struct { ErHa Cat } func test(){ cd := new(CatDog) /** * 虽然包含的两个组件都拥有Eat方法,但是层级不同, * ErHa的层级会比Cat深一层(说法可能不太正确,但确实可以描述问题), * 编译器会帮你调用到层级少的那个组件的Eat方法 */ cd.Eat() //此时调用Cat组件的Eat方法 } ``` ## 实际问题 ```go type AnimalAbstract interface { Eat() Run() } type Animal struct { } func (a *Animal)Eat(){ fmt.Println("animal eat!") } func (a *Animal)Run(){ fmt.Println("animal run!") } type Mammal struct { Animal power map[string]string } func (m *Mammal) Eat(){ fmt.Println("mammal eat!") m.power = make(map[string]string) } type Monkey struct { Mammal } func (m *Monkey)Run(){ fmt.Println("monkey run") m.power["run"] = "run" } type People1 struct { Mammal } type People2 struct { Monkey } type People3 struct { Mammal Monkey } func Exec(a AnimalAbstract){ /** * 传入People3时会报错,因为使用接口调用Eat()时实际调用到Mammal组件的Eat(), * 而调用Run时则实际调用到Monkey组件的Run(), 而Monkey组件的power并为初始化, * 所以触发panic, 在cpp中这种写法有重定义限制所以你可以很容易注意到这个问题, * 也可以使用虚继承来解决问题, 而golang则完全开放,把问题交给的程序员, * 如果不注意确实会踩坑(事例代码有些不切实际, 不过笔者在工作中确实碰到了这个问题, * 具体代码不方便展出) */ a.Eat() a.Run() fmt.Println("==========================") } func main(){ Exec(new(People1)) Exec(new(People2)) //People3会报错 Exec(new(People3)) } ```

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1029 次点击  
加入收藏 微博
2 回复  |  直到 2020-04-30 11:51:43
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传