【问题标题】:How to cast interface{} back into its original struct?如何将 interface{} 转换回其原始结构?
【发布时间】:2018-01-29 07:20:16
【问题描述】:

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

MyStruct  =>  Interface{}  => MyStruct

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

a.(MyStruct)

【问题讨论】:

  • Go 是静态类型的,所以如果你需要特定类型的结构,你必须知道编译时是什么类型
  • I don't know anything about the original struct besides what come inside the struct 什么意思?

标签: go struct types casting


【解决方案1】:

您至少需要知道它可能的类型。有几个案例, 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()
}

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

请注意,如果您想测试类型而不会惊慌失措,请执行s2, ok := thinger.(*MyStruct)。 ok 如果成功则为 true,否则为 false。

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

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

  1. 如果您真的对底层类型一无所知,您将不得不通过接口函数公开您需要的东西并调用它们。您可以在不了解底层类型的情况下执行此操作。

【讨论】:

    【解决方案2】:

    否:如this thread中所述

    Go 既不是协变的也不是逆变的。类型要么是equal,要么不是。

    您必须将结构拆开并处理碎片,或者use reflection
    类型断言只是“assertions”,而不是任何形式的“强制”。

    另见this thread,它提醒我们:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2021-12-21
      • 1970-01-01
      • 2021-08-06
      • 2018-12-25
      • 1970-01-01
      • 2017-04-11
      • 1970-01-01
      • 1970-01-01
      • 2015-04-30
      相关资源
      最近更新 更多