首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >golang通过反射从接口获取结构

golang通过反射从接口获取结构
EN

Stack Overflow用户
提问于 2015-12-15 01:13:55
回答 2查看 22.6K关注 0票数 7

原问题:

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

代码语言:javascript
复制
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

如果您只需直接传入struct,play示例就可以工作,因为可以传入实现特定接口的任何内容(在我的示例中,我只是使用空接口)。然而,我不知道如何将其视为底层的结构。

更新:

代码语言:javascript
复制
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

所以我想我现在的问题是,有没有一种机制可以访问可寻址/可设置的结构,而不必求助于副本?

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

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

EN

回答 2

Stack Overflow用户

发布于 2015-12-15 01:17:45

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

代码语言:javascript
复制
robot := &Robot{}
f(robot)

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

当您将robot分配给iface时,您就创建了robot值的副本。从iface获取对robot的引用是不可能的。

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

票数 4
EN

Stack Overflow用户

发布于 2018-04-12 07:33:38

你可以使用类型断言。

代码语言:javascript
复制
value, ok := i(Robot)
if ok {
    fmt.Println(value.Id)
}

从这个stackoverflow post

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34272837

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档