使用反射SetString [英] Using reflection SetString

查看:415
本文介绍了使用反射SetString的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  type ProductionInfo struct {
StructA [] Entry
}

类型条目结构{
Field1 string
Field2 int
}

我想使用反射更改 Field1 的值,但返回的反射对象总是 CanSet()=假。我能做什么?请参阅操场示例。



https:// play .golang.org / p / eM_KHC3kQ5



以下是代码:

  func SetField(source interface {},fieldName string,fieldValue string){
v:= reflect.ValueOf(source)
tt:= reflect.TypeOf(source)

for k:= 0; k< tt.NumField(); k){
fieldValue:= reflect.ValueOf(v.Field(k))

fmt.Println(fieldValue.CanSet())
if fieldValue.CanSet(){
fieldValue.SetString(fieldValue.String())
}
}
}

func main(){
source:= ProductionInfo { }
source.StructA = append(source.StructA,Entry {Field1:A,Field2:2})

SetField(source,Field1,NEW_VALUE)


解决方案

多重错误。让我们对它们进行迭代。



首先,您传递的值 ProductionInfo ,而不是<$ c $的值c> Entry 要修改的字段,所以首先将其更改为:

  SetField(source .StructA [0],Field1,NEW_VALUE)

接下来,非指针)值。你不能用反射修改非指针结构的字段,因为那样只会修改一个将被丢弃的副本。为了避免这种情况(并进一步混淆),这是不允许的( CanSet()返回 false )。所以你必须传递一个指向结构体的指针:

  SetField(& source.StructA [0],Field1, NEW_VALUE)

现在位于 SetField() reflect.ValueOf(source)将描述传入的指针。您可以使用 Value.Elem() 导航到 reflect.Value


$ b

  v:= reflect.ValueOf(source).Elem ()

现在它起作用了。修改后的代码:

  func SetField(source interface {},fieldName string,fieldValue string){
v:= reflect。 ValueOf(source).Elem()

fmt.Println(v.FieldByName(fieldName).CanSet())

如果v.FieldByName(fieldName).CanSet() {
v.FieldByName(fieldName).SetString(fieldValue)
}
}

func main(){
source:= ProductionInfo {}
source.StructA = append(source.StructA,Entry {Field1:A,Field2:2})

fmt.Println(Before:,source.StructA [0])
SetField(& source.StructA [0],Field1,NEW_VALUE)
fmt.Println(After:,source.StructA [0])
}

输出(在 Go Playground ):

 之前:{A 2} 
true
后:{NEW_VALUE 2}


I have a struct like this one:

type ProductionInfo struct {
    StructA []Entry
}

type Entry struct {
    Field1 string
    Field2 int
}

I would like to change the value of Field1 using reflection but the reflect object returned always CanSet() = false. What can I do? See playground example.

https://play.golang.org/p/eM_KHC3kQ5

Here is the code:

func SetField(source interface{}, fieldName string, fieldValue string) {
    v := reflect.ValueOf(source)
    tt := reflect.TypeOf(source)

    for k := 0; k < tt.NumField(); k++ {
        fieldValue := reflect.ValueOf(v.Field(k))

        fmt.Println(fieldValue.CanSet())
        if fieldValue.CanSet() {
            fieldValue.SetString(fieldValue.String())
        }
    }
}

func main() {
    source := ProductionInfo{}
    source.StructA = append(source.StructA, Entry{Field1: "A", Field2: 2})

    SetField(source, "Field1", "NEW_VALUE")
}

解决方案

Multiple errors. Let's iterate over them.

First, you pass a value of ProductionInfo and not a value of Entry whose field you want to modify, so first change it to:

SetField(source.StructA[0], "Field1", "NEW_VALUE")

Next, you are passing a (non-pointer) value. You can't modify the fields of a non-pointer struct with reflection, because that would only modify a copy which would be discarded. In order to avoid this (and further confusion), this is not allowed (CanSet() returns false). So you have to pass a pointer to the struct:

SetField(&source.StructA[0], "Field1", "NEW_VALUE")

Now inside SetField() the reflect.ValueOf(source) will describe the passed pointer. You may use Value.Elem() to navigate to the reflect.Value of the pointed object (the struct value):

v := reflect.ValueOf(source).Elem()

And now it works. Modified code:

func SetField(source interface{}, fieldName string, fieldValue string) {
    v := reflect.ValueOf(source).Elem()

    fmt.Println(v.FieldByName(fieldName).CanSet())

    if v.FieldByName(fieldName).CanSet() {
        v.FieldByName(fieldName).SetString(fieldValue)
    }
}

func main() {
    source := ProductionInfo{}
    source.StructA = append(source.StructA, Entry{Field1: "A", Field2: 2})

    fmt.Println("Before: ", source.StructA[0])
    SetField(&source.StructA[0], "Field1", "NEW_VALUE")
    fmt.Println("After: ", source.StructA[0])
}

Output (try it on the Go Playground):

Before:  {A 2}
true
After:  {NEW_VALUE 2}

这篇关于使用反射SetString的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆