【问题标题】:Dynamic Type Assertion Golang动态类型断言 Golang
【发布时间】:2019-01-01 10:26:48
【问题描述】:

我正在尝试将接口动态转换回其原始结构,但在转换后访问结构的属性时遇到问题。

以这段代码为例。

package main

import (
    "fmt"
    "log"
)

type struct1 struct {
    A string
    B string
}

type struct2 struct {
    A string
    C string
}

type struct3 struct {
    A string
    D string
}

func main() {
    s1 := struct1{}
    s1.A = "A"
    structTest(s1)

    s2 := struct2{}
    s2.A = "A"
    structTest(s2)

    s3 := struct3{}
    s3.A = "A"
    structTest(s3)
}

func structTest(val interface{}) {
    var typedVal interface{}

    switch v := val.(type) {
    case struct1:
        fmt.Println("val is struct1")
    case struct2:
        fmt.Println("val is struct2")
    case struct3:
        fmt.Println("val is struct3")
    default:
        log.Panic("not sure what val is.")
    }

    fmt.Println(typedVal.A)
}

我希望能够将 3 种已知结构类型之一传入我的函数。然后找出传入的结构类型来键入断言它。最后,我希望能够访问类似的属性。

基本上我想在我的结构中有一些基本的继承,但到目前为止似乎不可能在 go 中做到这一点。我看到一些帖子提到使用接口进行继承,但我的结构没有方法,所以我不确定如何使用接口。

这样的事情在go中可能吗?

【问题讨论】:

  • 为什么不从函数中返回值。你这样做是正确的,只需返回值以获取结构,然后根据需要使用它。
  • Go 中没有继承(我不确定“使用接口的继承”是什么意思,因为接口实现了一种多态形式)。如果您正在寻找继承,那么您就是在尝试使用错误的工具来解决问题。
  • @Himanshu 这是我正在尝试做的一个简化示例。我想我可以获取这些值并将它们返回到地图或其他东西中。当我从每个结构中获取相同的东西但我必须为每个开关选项复制粘贴它时,这似乎很浪费。
  • @jhall1990 如果不知道接口可以包含什么类型然后使用 switch 来检查,这是不可能检查接口的底层类型的。因此,您可以使用键作为名称和值作为结构的映射。这样,您将根据键了解结构并将其传递给函数。
  • 如果这不是您真正的用例,那是什么。看来我误解了您的问题,您能否详细说明一下以便我们能够更好地为您提供帮助?

标签: go


【解决方案1】:

我希望能够将 3 种已知结构类型之一传入我的函数。然后找出传入哪个结构类型来键入断言它。最后,我希望能够访问类似的属性。

您可以使用类型断言来做到这一点。基本思想是,在任何类型切换的情况下,只需使用类型断言来获取相应类型的具体实例,然后您就可以调用任何您想要的属性。

看看下面的例子

package main

import (
    "fmt"
)

type test1 struct {
    A, B string
}

type test2 struct {
    A, C string
}

func testType(val interface{}) {
    switch val.(type) {
    case test1:
        t := val.(test1)
        fmt.Println(t.B)
        break
    case test2:
        t := val.(test2)
        fmt.Println(t.C)
        break
    }
}

func main() {
    t1, t2 := test1{B: "hello"}, test2{C: "world"}
    testType(t1)
    testType(t2)
}

Playground

【讨论】:

    【解决方案2】:

    您的代码中的函数 structTest(val interface{}) 似乎是松散类型的。你向它传递一个无类型的参数并期望它满足某些条件(将具有字段 A),它在任何类型的语言中看起来都很奇怪。

    使用接口这种多态性,在我看来,在 Go 中可以表达为

    package main
    
    import (
        "fmt"
        "log"
    )
    
    type A string
    type HasA interface {
        PrintA()
    }
    
    func (a A) PrintA() { fmt.Println(a) }
    
    type struct1 struct {
        A
        B string
    }
    
    type struct2 struct {
        A
        C string
    }
    
    type struct3 struct {
        A
        D string
    }
    
    func main() {
        s1 := struct1{}
        s1.A = "A"
        structTest(s1)
    
        s2 := struct2{}
        s2.A = "A"
        structTest(s2)
    
        s3 := struct3{}
        s3.A = "A"
        structTest(s3)
    }
    
    func structTest(val HasA) {
    
        switch val.(type) {
        case struct1:
            fmt.Println("val is struct1")
        case struct2:
            fmt.Println("val is struct2")
        case struct3:
            fmt.Println("val is struct3")
        default:
            log.Panic("not sure what val is.")
        }
    
        val.PrintA()
    }
    

    Playground

    【讨论】:

      猜你喜欢
      • 2014-01-22
      • 2019-11-03
      • 1970-01-01
      • 2015-03-10
      • 2014-01-08
      • 1970-01-01
      • 2014-01-12
      • 2017-02-13
      • 2019-01-19
      相关资源
      最近更新 更多