Golang用内嵌实现继承的方法

今天和一个同事一起review代码,看他又写用embedded struct抽公共代码,稍微吐槽了一下。唠唠叨叨,骂骂咧咧地bb了好久,反正他也没听进去。

刚开始写go那会儿,我也傻傻的照着网上的《用内嵌实现继承的方法》这类博客去写公共代码。但有句话叫go语言没有继承(Go has no inheritance.)也不是说go不需要继承,过载,面向对象,阿巴阿巴。就是现在的项目就是go写的,打工人写就完事儿了。但想想go就是tmd没有继承!

有些代码有点重复写就写了,这样好改啊(雅言叫可维护性强)

看这么个例子, 比与A和B都有Fixed,给抽它个公共struct。

type ProductA struct {
    Embedded
    Flexible int `json:"flexible"`
}
type ProductB struct {
    Embedded
    Flexible string `json:"flexible"`
}
type Embedded struct {
    Fixed int `json:"fixed" validate:"required,gte=10,lte=20`
}

// 随便写个方法
func (e Embedded) add() int {
    return e.Fixed + 1
}

写的挺好的公共类, 但有一天业务变了。A里面的校验10到20不变,B改了改成10到30了。除了把Fixed分别写道A和B,还可以把validate tag拿掉,写个类方法简单校验一下。
但设想一下真实的业务场景,Embedded其实挺复杂的,有好些field在里面。有好些类方法还用到了Fixed和其他的field。这tmd重构一下就伤筋动骨,肯定不会为了一个小校验,把Embedded移除。
还有这个让人绝望的问答,应该很多写go的新手也都想过struct tag怎么用变量吧。毕竟不是java annotation,没那么多功能。Go就是这么一个古朴的语言,就是写着写着就觉得好像应该有这么个功能吧,别的语言都有啊,但好像没见别人这么写过啊(不祥的预感)。。。woc,不能这么写。
就像有个动图,是用多光标快速给多个类型写比较大小还是啥的,讽刺go语言的copy hell。不过写go真的难免多copy。
比如写java经常搞一些Dog extends Animal, Cat extends Animal,写个Animal.eat(),再写个Dog.eat(),再super()啥的。把it作为母类,extends出来he和she然后写it is as it is, he is as it is, she is as it is
生搬硬套到golang就不大行。搁这里要写个type Eater interface。没那么多抽象结构,就硬写it ishe isshe is 简单直接

尽量别整embedded struct搞继承 多为之后改代码的人考虑(官话叫可维护性强)

再举个例子
接着刚才Fixed校验的方法,我要返回json结果体中fixed字段不对。

func (e Embedded) validate() error {
    // 校验代码
    // 通过return nil
    // ....
    // 校验失败
    return FieldError("fixed") //FieldError 返回用户错误提示信息
}

但是这么写的话,如果要修改Embedded.Fixed 的json字段名称,就有两处代码要修改,而且很容易改漏。

type Embedded struct {
    Fixed int `json:"fixed_value"`
}
func (e Embedded) validate() error {
    // 校验代码
    // 通过return nil
    // ....
    // 校验失败
    return FieldError("fixed") //FieldError 返回用户错误提示信息
}

就比如领导说了把fixed改成fixed_value,然后校验那里就改漏了,也没啥静态检查啥的。这两个值一个是struct tag的一部分,一个是代码里面的一个string常量。对于go来说他们没啥关系,没有必要在struct tag里面使用变量啊?又不是不能用,是不是?go就是这么朴素的语言。

我也想过用reflect,但简单说还还是不好用,因为Embedded.Fixed这种语法也不存在, 只能是

e := Embedded{}
e.Fixed ...

https://stackoverflow.com/questions/29752462/using-a-variable-in-the-struct-tag
算了不骂了,睡吧 明天还要打工。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容