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

时间:2017-01-15 12:02:22

标签: go struct types casting

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

MyStruct  =>  Interface{}  => MyStruct

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

a.(MyStruct)

2 个答案:

答案 0 :(得分:4)

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

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

    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,否则为false。

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

      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. 如果你真的不了解底层类型,你必须通过接口函数公开你需要的东西并调用它们。您可以在不了解基础类型的情况下做到这一点。

答案 1 :(得分:2)

否:如this thread

中所述
  

Go既不是协变也不是逆变。类型可以是 equal ,也可能不是

     

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

另见this thread,它提醒我们:

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

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

     

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

这会使从界面到具体类型的转换变得非常困难。