如何将 interface{} 转换回其原始结构?

kam*_*mbi 3 struct types casting go

我需要一种将结构/接口动态转换回其原始对象的方法。我可以在里面添加方法/函数。基本上我需要这样的东西:

MyStruct  =>  Interface{}  => MyStruct
Run Code Online (Sandbox Code Playgroud)

在最终转换时,除了结构内部的内容之外,我对原始结构一无所知,所以我不能这样:

a.(MyStruct)
Run Code Online (Sandbox Code Playgroud)

Ste*_*oka 8

您至少需要知道它可能的类型。有几种情况, 1. 你认为你可能知道它是什么。2. 你有一个可能的类型列表, 3. 你的代码对底层类型一无所知。

  1. 如果您认为自己知道,则可以使用类型断言将其转换回原始结构类型。

...

package main

import (
    "fmt"
)

type MyStruct struct {
  Thing string
}

func (s *MyStruct) Display() {
  fmt.Println(s.Thing)
}

type Thingable interface {
  Display()
}

func main() {
  s := &MyStruct{
    Thing: "Hello",
  }

  // print as MyThing
  s.Display()

  var thinger Thingable
  thinger = s

  // print as thingable interface
  thinger.Display()

  // convert thinger back to MyStruct
  s2 := thinger.(*MyStruct) // this is "type assertion", you're asserting that thinger is a pointer to MyStruct. This will panic if thinger is not a *MyStruct

  s2.Display()
}
Run Code Online (Sandbox Code Playgroud)

你可以在这里看到这个:https : //play.golang.org/p/rL12Lrpqsyu

请注意,如果您想在错误的情况下不惊慌地测试类型,请执行s2, ok := thinger.(*MyStruct). 如果成功则确定为真,否则为假。

  1. 如果要针对一堆类型测试接口变量,请使用开关:(滚动到底部)

...

package main

import (
    "fmt"
    "reflect"
)

type MyStruct struct {
    Thing string
}

type MyStruct2 struct {
    Different string
}

func (s *MyStruct) Display() {
    fmt.Println(s.Thing)
}

func (s *MyStruct2) Display() {
    fmt.Println(s.Different)
}

type Thingable interface {
    Display()
}

func main() {
    s := &MyStruct{
        Thing: "Hello",
    }

    // print as MyThing
    s.Display()

    var thinger Thingable
    thinger = s

    // print as thingable interface
    thinger.Display()

    // try to identify thinger
    switch t := thinger.(type) {
    case *MyStruct:
        fmt.Println("thinger is a *MyStruct. Thing =", t.Thing)
    case *MyStruct2:
        fmt.Println("thinger is a *MyStruct2. Different =", t.Different)
    default:
        fmt.Println("thinger is an unknown type:", reflect.TypeOf(thinger))
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以在这里试试https://play.golang.org/p/7NEbwB5j6Is

  1. 如果您真的对底层类型一无所知,则必须通过接口函数公开您需要的东西并调用它们。很有可能你可以在不了解底层类型的情况下做到这一点。


Von*_*onC 3

否:正如本线程中提到的

Go 既不是协变也不是逆变。类型要么相等,要么不相等。

您必须将结构拆开并处理各个部分,或者使用反射
类型断言只是“断言”,而不是任何类型的“强制”。

另请参阅此线程,它提醒我们:

  • 指针是一种类型。
  • 结构体是另一种类型。
  • 整数是另一种类型。
  • 浮点数是另一种类型。
  • 布尔值是另一种类型。

接口的原则涉及附加到类型的方法T,而不是类型T是什么。

接口类型由一组方法定义。
实现这些方法的任何值都可以分配给该类型的接口值。

这将使从接口到具体类型的转换变得非常困难。