繁体   English   中英

如何使用反射设置作为指向任意值的指针的结构成员

[英]How to set a struct member that is a pointer to an arbitrary value using reflection

注意:我想做与如何在 Go 中使用反射设置一个指向字符串的指针的结构成员相同,但以更通用的方式。 现有问题并不能解决我的问题。

我有我想使用反射填充的不同类型字段的结构:

type MyStruct struct {
    SomeInt       int
    SomeString    string
    SomeIntPtr    *int
    SomeStringPtr *string
}

我想写入各个字段的值是从配置存储中检索并解析为正确的类型,类似于:

func getValueForField(fieldName string) interface{}

对于int*int类型,该函数返回一个int (包装在接口中)。 对于string*string ,该函数为所有类型返回string (在接口后面)等等。

- >请注意,它返回*int / *string

现在我想将值分配给结构字段:

var field reflect.Value  = reflect.ValueOf(ptrToMyStruct).Elem().Field(i)
var value interface{}    = getValueForField(....)
var isPointer bool       = field.Kind() == reflect.Ptr

// assign "value" to "field":
if isPointer {
    // ??
    field.Set(reflect.ValueOf(value).Addr()) // panic: reflect.Value.Addr of unaddressable value
} else {
    field.Set(reflect.ValueOf(value)) // works
}

将这些值分配给具体类型很容易并且按预期工作。 但是我不能在没有以某种方式获取地址的情况下将int类型(从getValueForField返回)分配给*int字段。 由于我只有一个interface{} ,这需要通过反射来完成。

这是 Go Playground 的链接: https : //play.golang.org/p/zElEGHgx1IO

使用reflect.New()为字段构造一个新的指针值,从value设置指向的value ,然后将这个新值设置到指针字段。

例如:

type MyStruct struct {
    SomeIntPtr    *int
    SomeStringPtr *string
}

var ms MyStruct

// Set int pointer
{
    var i interface{} = 3 // of type int

    f := reflect.ValueOf(&ms).Elem().FieldByName("SomeIntPtr")
    x := reflect.New(f.Type().Elem())
    x.Elem().Set(reflect.ValueOf(i))
    f.Set(x)
}

// Set string pointer
{
    var i interface{} = "hi" // of type string

    f := reflect.ValueOf(&ms).Elem().FieldByName("SomeStringPtr")
    x := reflect.New(f.Type().Elem())
    x.Elem().Set(reflect.ValueOf(i))
    f.Set(x)
}

fmt.Println("ms.SomeIntPtr", *ms.SomeIntPtr)
fmt.Println("ms.SomeStringPtr", *ms.SomeStringPtr)

这将输出(在Go Playground上尝试):

ms.SomeIntPtr 3
ms.SomeStringPtr hi

所以你的代码可能是这样的:

// assign "value" to "field":
if isPointer {
    x := reflect.New(field.Type().Elem())
    x.Elem().Set(reflect.ValueOf(value))
    field.Set(x)
} else {
    field.Set(reflect.ValueOf(value)) // works
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM