动态类型断言Golang

时间:2018-07-24 17:43:48

标签: go

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

以该代码为例。

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种已知结构类型之一传递给我的函数。然后找出传入的结构类型以对它进行断言。最后,我希望能够访问类似属性。

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

这样可以吗?

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

您代码中的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