简体   繁体   English

动态类型断言Golang

[英]Dynamic Type Assertion Golang

I'm trying to convert an interface dynamically back to it's original struct but I am having issues accessing attributes of the struct after the conversion. 我正在尝试将接口动态地转换回其原始结构,但在转换后访问结构的属性时遇到问题。

Take this code for example. 以下面的代码为例。

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)
}

I would like to be able to pass in one of 3 known struct types into my function. 我希望能够将3种已知结构类型之一传递给我的函数。 Then figure out which struct type was passed in to type assert it. 然后找出传入的结构类型以对它进行断言。 Finally I want to be able to access like attributes. 最后,我希望能够访问类似属性。

Basically I want to have some basic inheritance in my structs, but so far it seems that it is not possible to do this in go. 基本上,我想在我的结构中拥有一些基本的继承,但是到目前为止,似乎不可能随时进行。 I saw some posts mentioning inheritance using an interface, but my structs have no methods so I'm not sure how I would use an interface. 我看到一些文章提到使用接口继承,但是我的结构没有方法,所以我不确定如何使用接口。

Is something like this possible in go? 这样的事情可能发生吗?

I would like to be able to pass in one of 3 known struct types into my function. 我希望能够将3种已知结构类型之一传递给我的函数。 Then figure out which struct type was passed in to type assert it. 然后找出传入的结构类型以对它进行断言。 Finally I want to be able to access like attributes. 最后,我希望能够访问类似属性。

You can use type assertions to do exactly that. 您可以使用类型断言来做到这一点。 Basic idea is, in any case of the type switch just use type assertion to get a concrete instance of the corresponding type and then you can call whatever properties that you wish. 基本思想是,在任何情况下,类型开关都只需要使用类型断言来获取对应类型的具体实例,然后就可以调用所需的任何属性。

Take a look at the following example 看下面的例子

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 操场

Function structTest(val interface{}) in your code seems to be loosely typed. 代码中的函数structTest(val interface {})似乎是松散键入的。 You pass it an untyped argument and expect it will satisfy some condition (will have field A), it looks strange in any typed language. 您将其传递为无类型参数,并期望它满足某些条件(将具有字段A),在任何类型的语言中它看起来都很奇怪。

Using an interface this kind of polymorphism, in Go, to my mind, can be expressed something like 在我看来,使用接口,这种多态性可以表达为

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 操场

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM