我继承了一些看起来像这样的代码:type FooWrapper struct { Stuffer interface{ GetStuff() *grpc.Stuff } Thinger interface{ GetThing() *grpc.Thing } Widgeter interface{ GetWidget() *grpc.Widget } // many more like these}func NewFooWrapper(v proto.Message) FooWrapper { var w FooWrapper w.Stuffer, _ = v.(interface{ GetStuff() *grpc.Stuff }) w.Thinger, _ = v.(interface{ GetThing() *grpc.Thing }) w.Widgeter, _ = v.(interface{ GetWidget() *grpc.Widget }) // many more like these return w}func (w FooWrapper) GetStuff() *grpc.Stuff { if w.Stuffer == nil { return nil } return w.Stuffer.GetStuff()}// many more methods like this one我们可以看到这段代码做了以下事情:它声明了一个FooWrapper带有一堆匿名接口字段的结构,每个接口字段对应一个可能存在于任何实现中的方法proto.Message。NewFooWrapper构造函数正在转换v为这些匿名接口类型中的每一种,从而丢弃错误。因此,如果框入的类型v没有GetXXX方法,则相关字段w将简单地为nilFooWrappergetter 检查相应的字段是否存在nil,如果不是,它会调用装箱值的方法。对我来说,这似乎是实现类型切换的一种非常冗长的方式,尽管我不确定这是惯用的 Go 代码。但是我想它在必须传递给多个不相关的方法的情况下可能很有用v,导致类型切换被复制粘贴到任何地方(这不是我在这里得到的代码的情况)。实际上,此代码是否等效于类型开关?使用这种模式而不是类型开关有什么好处?
1 回答
繁星coding
TA贡献1797条经验 获得超4个赞
一句话,“不”,这不是惯用语。但这当然并不意味着它是“错误的”。
尽管考虑到匿名接口类型是重复的,但这样做似乎很愚蠢,而不是命名类型。
如果我继承了该代码,我会立即更改它。
考虑到确切的代码示例,我还将重新定义我的结构以使用嵌入式接口:
type Stuffer interface { GetStuff() *grpc.Stuff }
type Thinger interface { GetThing() *grpc.Thing }
type Widgeter interface { GetWidget() *grpc.Widget }
type FooWrapper struct {
Stuffer
Thinger
Widgeter
// many more like these
}
- 1 回答
- 0 关注
- 104 浏览
添加回答
举报
0/150
提交
取消