首页 > 解决方案 > go中的类型转换

问题描述

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

type Nested struct {
  Value string
}

type TypeA struct {
  Nested
  Foo string
}

type TypeB struct {
  Nested
  Bar string
}

我必须实现以下回调:

func Callback(param interface{}) {

}

param可以是*TypeA*TypeB

如何转换 type-convert/cast 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

提前感谢您的帮助。

标签: gotype-conversion

解决方案


如果 in 中的动态值param是 type *misc.TypeA,则只能键入 assert *misc.TypeA

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

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

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

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()为接受此接口类型的值。而且由于您已经在使用嵌入(NestedintoTypeATypeB),因此可以方便地GetNested()在其自身上实现一次此功能Nested

func (n Nested) GetNested() Nested {
    return n
}

type HasNested interface {
    GetNested() Nested
}

func Callback(nst HasNested) {
    fmt.Println(nst.GetNested().Value)
}

就这样。这将再次输出相同的内容。在Go Playground上试试这个。


推荐阅读