Go 转换到多个匿名接口是否等同于类型开关?

Go 转换到多个匿名接口是否等同于类型开关?,go,interface,type-conversion,type-switch,Go,Interface,Type Conversion,Type Switch,我继承了如下代码: 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.Messa

我继承了如下代码:

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中的相关字段将只是nil FooWrapper getter检查对应字段是否为nil,如果不是,则调用装箱值上的方法。 对我来说,这似乎是实现类型开关的一种非常冗长的方式,尽管我不确定这是否是惯用的Go代码

然而,我想它在必须将v传递给多个不相关的方法的情况下可能会很有用,这会导致类型开关被复制粘贴到任何地方。这里的代码不是这样的

实际上,该代码是否等同于类型开关


使用这种模式而不是类型开关有什么好处?

总之,不,它不是惯用的。当然,这并不意味着这是错误的

尽管考虑到匿名接口类型是重复的,但这样做似乎相当愚蠢,而不是使用命名类型

如果我继承了该代码,我会立即更改它

考虑到这个确切的代码示例,我还将重新定义我的结构以使用嵌入式接口:

类型填充器接口{GetStuff*grpc.Stuff} 键入Thinger接口{GetThing*grpc.Thing} 键入Widgeter接口{GetWidget*grpc.Widget} 类型FooWrapper结构{ 填充器 Thinger 维吉特 //更多像这样的 }
什么是惯用的是一个很大程度上主观的问题,但是除了空接口{}之外,通常不经常看到匿名接口,主要是因为它们通常不是很有用,所以我个人不认为它们是惯用的。@Adrian惯用的是一个很大程度上主观的问题,在围棋的背景下,似乎有一些明确的目的,就是提供关于围棋的提示。引用:本文档提供了编写清晰、惯用的Go代码的技巧。但什么是惯用语——就这一点而言,什么是明确的——仍然是主观的。事实上,这句话清楚地表明,它提供的是提示,而不是规则。标准库在处理错误时使用匿名接口,并记录其中的一些用法。我不知道这是否说明这个练习是否地道,但我认为值得注意。