我继承了一些看起来像这样的代码:
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
带有一堆匿名接口(interface)字段的结构体,每个方法一个可能存在于 proto.Message
的任何实现中. NewFooWrapper
构造函数正在转换 v
到这些匿名接口(interface)类型中的每一种,丢弃错误。因此,如果 v
中的类型被装箱没有 GetXXX
方法,相关字段在w
将只是 nil
FooWrapper
getter 检查对应的字段是否为 nil
如果不是,它会调用装箱值的方法。 对我来说,这似乎是实现类型切换的一种非常冗长的方式,尽管我不确定这是惯用的 Go 代码。
但是我想它在
v
的情况下可能很有用。必须传递给多个不相关的方法,导致类型切换被复制粘贴到任何地方(这不是我在这里得到的代码的情况)。实际上,此代码是否等效于类型开关?
使用这种模式而不是类型开关有什么好处?
最佳答案
一句话,“不”,这不是惯用语。但这当然并不意味着它是“错误的”。
尽管考虑到匿名接口(interface)类型是重复的,但这样做似乎很愚蠢,而不是命名类型。
如果我继承了该代码,我会立即更改它。
考虑到确切的代码示例,我还将重新定义我的结构以使用嵌入式接口(interface):
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
}
关于go - 转换为多个匿名接口(interface)是否等同于类型切换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62660024/