代码之家  ›  专栏  ›  技术社区  ›  blackgreen VonC

在Go中转换为匿名接口是否符合习惯?

  •  -1
  • blackgreen VonC  · 技术社区  · 6 年前

    我继承了一些看起来像这样的代码:

    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
    

    我们可以看到这段代码执行了以下操作:

    1. 它宣布 FooWrapper 带有一堆匿名接口字段的结构,每个字段对应一个可能存在于任何实现中的方法 proto.Message .
    2. 这个 NewFooWrapper 构造函数正在转换 v 对于每种匿名接口类型,丢弃错误。因此,如果装箱的类型 v 没有 GetXXX 方法,相关领域 w 将只是 nil
    3. FooWrapper getter检查相应的字段是否为 如果不是,它将调用盒装值的方法。

    在我看来,这似乎是一种相当冗长的实现类型切换的方法,尽管我不确定这是否是惯用的Go代码。

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

    在实践中,这段代码是否等同于类型开关?

    使用这种模式而不是类型切换有什么优点?

    0 回复  |  直到 6 年前
        1
  •  3
  •   Jonathan Hall    6 年前

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

    尽管匿名接口类型是重复的,但这样做似乎很愚蠢,而不是命名类型。

    如果我继承了这段代码,我会立即更改它。

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

    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
    }
    
    推荐文章