reflection - golang 通过反射从接口(interface)获取结构

标签 reflection go

原始问题:

我正在尝试进行一些反序列化,但我对在传入接口(interface)时如何访问结构感到有点困惑。

package main

import (
    "fmt"
    "reflect"
)

type Robot struct {
    Id int
}

func f(i interface{}) {
    v := reflect.ValueOf(i).Elem().FieldByName("Id")
    fmt.Println("fields: ", reflect.ValueOf(i).Elem().NumField()) 
    ptr := v.Addr().Interface().(*int)
    *ptr = 100
}

func main() {
    robot := Robot{}

    var iface interface{} = robot // if I omit this line and pass in robot this works
    f(&iface)
    fmt.Println(robot.Id) //I want to get here 100

}

http://play.golang.org/p/y6UN3KZxRB

如果您只是直接传入结构,播放示例就可以运行,但是因为可以传入实现特定接口(interface)的任何内容(在我的示例中,我只是使用空接口(interface))。但是我不知道如何将其视为下面的结构。

更新:

package main

import (
    "fmt"
    "reflect"
)

type MessageOne struct {
    Header   string `FixedWidth:0,4`
    FieldOne string `FixedWidth:"4,4"`
    FieldTwo string `FixedWidth:"8,4"`
}

type MessageTwo struct {
    FieldX string `FixedWidth:"X,Y"`
    FieldY string `FixedWidth:"X,Y"`
}

var (
    messageMap = map[string]interface{}{
        "msg1": MessageOne{FieldOne: "testValueUnchanged"},
        "msg2": MessageTwo{},
    }
)

func deserialize(input string, i interface{}) interface{} {
    value := reflect.ValueOf(i)
    fmt.Println("1st Value Type: ", value.Kind())
    // unswarp ptr
    value = value.Elem()
    fmt.Println("Unwrapped: ", value.Kind())
    value = value.Elem()
    fmt.Println("Unwrapped: ", value.Kind())

    // Create a copy that I can set?
    copyValue := reflect.New(value.Type()).Elem()
    fmt.Println("Orig Struct is settable", value.CanSet())
    fmt.Println("Orig StructField0 is settable", value.Field(0).CanSet())

    fmt.Println("Copy is: ", copyValue.Kind())
    fmt.Println("Copy Struct is settable", copyValue.CanSet())
    fmt.Println("Copy StructField0 is settable", copyValue.Field(0).CanSet())
    fmt.Println("Orig struct type is: ", value.Type())
    fmt.Println("Copy struct type is: ", copyValue.Type())

    copyValue.Field(1).SetString("testValueChanged")

    return copyValue.Interface()
}

func GetMessageFromInput(input string) interface{} {
    selector := input[0:4]
    fmt.Println(selector)
    field := messageMap[selector]
    return deserialize(input, &field)
}

func main() {
    val := messageMap["msg1"]

    serializedData := "msg1.012345678"

    deserializedVal := GetMessageFromInput(serializedData)

    //msg1 := deserializedVal.(MessageOne)

    fmt.Printf("Orig: %+v \nReceived: %+v", val, deserializedVal)
}

http://play.golang.org/p/Cj9oPPGSLM

我想复制我的结构,从而从这里获得一个可寻址的实例:https://gist.github.com/hvoecking/10772475

所以我想我现在的问题是,是否有一种机制可以访问可寻址/可设置的结构而无需诉诸副本?

潜在的问题是采用字符串(实际上是字节数组)并让结构具有必要的信息来有效地反序列化它,而不必编写几十个反序列化函数,这很容易维护。因此,这些示例结构中的标签未在示例问题中解决,但访问结构标签字段将提供从输入字节填充结构的偏移量。显然我还没有走到那一步。在这里我感到沮丧的部分原因是,我似乎非常努力地工作却没有取得多大进展,而且我觉得我在这个过程中没有学到很多东西。

一些额外的游戏编辑让我找回了我的标签: http://play.golang.org/p/2DbbWLDKPI

最佳答案

你不想传递一个指向接口(interface)的指针,你想传递一个指向你的结构本身的指针。

robot := &Robot{}
f(robot)

http://play.golang.org/p/owv-Y4dnkl

当您将 robot 分配给 iface 时,您创建了 robot 值的副本。无法从 iface 获取对 robot 的引用。

当您传入 f(&iface) 时,对 reflect.ValueOf(i).Elem() 的调用只是返回内部 iface 值,而不是 Robot 结构值。

关于reflection - golang 通过反射从接口(interface)获取结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34272837/

相关文章:

c# - 在构造函数中使用反射设置数据类的属性

java - 使用Java反射获取类数组的类型

node.js - 在 Node.js 中获取 256 位 AES GCM 加密的正确标签时遇到问题

go - 使用 golang 1.10.2 使用 IKEv2 证书连接到 socks5 代理

json - 将查询参数添加到 Go Json Rest

java - 枚举的值来自其名称

c# - 使用反射创建枚举

c# - 在使用属性之前动态查找使用过的属性

methods - T 和 *T 的方法集

for-loop - Go中for循环内的错误处理可能会导致下一次迭代