【问题标题】:type conversion in gogo中的类型转换
【发布时间】:2020-10-12 07:24:42
【问题描述】:

我是新手,在访问运行时未知的结构数据时遇到问题:

type Nested struct {
  Value string
}

type TypeA struct {
  Nested
  Foo string
}

type TypeB struct {
  Nested
  Bar string
}

我必须实现以下回调:

func Callback(param interface{}) {

}

param 可以是*TypeA*TypeB

如何转换类型转换/转换param,以便我可以访问这两种类型共有的已知Nested 元素?

因为接口是隐式实现的,我想我可以做这样的事情

type Whatever struct {
  Nested
}

然后

func Callback(param interface{}) {
  nst := param.(*Whatever)
  fmt.Printf(nst.Nested.Value)
}

然而这会导致

interface {} is *misc.TypeA, not *misc.Whatever

提前感谢您的帮助。

【问题讨论】:

    标签: go type-conversion


    【解决方案1】:

    如果param中的动态值为*misc.TypeA类型,则只能type assert*misc.TypeA

    这样做,然后您可以访问Nested 字段:

    func Callback(param interface{}) {
        nst := param.(*TypeA)
        fmt.Printf(nst.Nested.Value)
    }
    

    如果它可以是更多类型的值,请使用type switch

    func Callback(param interface{}) {
        switch nst := param.(type) {
        case *TypeA:
            fmt.Println(nst.Nested.Value)
        case *TypeB:
            fmt.Println(nst.Nested.Value)
        }
    }
    

    测试它:

    a := &TypeA{
        Nested: Nested{Value: "val"},
    }
    Callback(a)
    b := &TypeB{
        Nested: Nested{Value: "val"},
    }
    Callback(b)
    

    输出(在Go Playground上试试):

    val
    val
    

    如果你打算在所有情况下都这样做,你可以像这样减少代码:

    func Callback(param interface{}) {
        var nst Nested
        switch x := param.(type) {
        case *TypeA:
            nst = x.Nested
        case *TypeB:
            nst = x.Nested
        }
        fmt.Println(nst.Value)
    }
    

    这将输出相同的内容。在Go Playground 上试试吧。

    当然最好的办法是使用接口。使用带有GetNested() Nested 方法的接口,并让您的类型实现它。并更改Callback() 以接受此接口类型的值。而且由于您已经在使用嵌入(NestedTypeATypeB),因此在 Nested 本身上实现这个 GetNested() 函数很方便:

    func (n Nested) GetNested() Nested {
        return n
    }
    
    type HasNested interface {
        GetNested() Nested
    }
    
    func Callback(nst HasNested) {
        fmt.Println(nst.GetNested().Value)
    }
    

    仅此而已。这将再次输出相同的内容。在Go Playground 上试试这个。

    【讨论】:

    • 感谢您的回答@icza。问题是,回调和类型都来自我正在使用的库,而不是我自己的代码。所以我必须接受现状。
    • @gofrm 那么上面介绍的类型切换对你来说是最方便的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-12
    • 1970-01-01
    • 1970-01-01
    • 2014-05-25
    • 1970-01-01
    • 1970-01-01
    • 2013-11-03
    相关资源
    最近更新 更多