dongzhabo2796 2015-01-23 17:53
浏览 16
已采纳

通过Go中的反射为结构成员分配值

I have a struct v with members A, B, C string. Using reflection, I can get the names of the fields and their values:

typ := v.Type()
for i := 0; i < v.NumField(); i++ {
    // gets us a StructField
    fi := typ.Field(i)
    fieldname := fi.Name
    fmt.Println(fieldname)
    val := fmt.Sprintf("%v", v.Field(i).Interface())
 }

since I have the name, and can get the value OUT, can I assign new values to the fields? I would like to do essentially:

v.Field(fieldname).Interface() = "new value"

but that obviously doesn't work. Is it possible to assign a value into a struct if you only know the name of the field?

In practice, I'm trying to assign values from a map[string]string to corresponding fields in a struct, where the struct and map definitions may expand of change over time, and the map may contain more, or less, values than the struct. I've considered doing it w/JSON, but that approach leaves me a little cold, seeing as how easy it was to use reflection to get "almost" there!

Thanks, Ken

  • 写回答

1条回答 默认 最新

  • doumu9799 2015-01-23 18:07
    关注

    Yes, it is possible.

    Introduction

    Since you want to access and modify the value of a variable (or field), you need to use the reflect.Value type instead of reflect.Type. You can acquire it with reflect.ValueOf(). Also in order to modify it with reflection, you need to pass the address (a pointer) of the struct or value you want to modify (else you could only read it but not modify it).

    But you don't want to modify the address/pointer but the pointed value, so you have to "navigate" from the Value of the pointer to the Value of the pointed variable (struct), this is what Value.Elem() is for. It looks like this: reflect.ValueOf(&s).Elem()

    You can get the Value of a struct field with the Value.FieldByName() method, which since we passed the address of the pointer to the ValueOf() function will be settable.

    The Code

    The code is much simpler than the introduction once you understand it. You can also try it on the Go Playground:

    var s struct {
        A, B, C string
    }
    s.A, s.B, s.C = "a1", "b2", "c3"
    
    fmt.Println("Before:  ", s)
    
    v := reflect.ValueOf(&s).Elem()
    
    v.FieldByName("A").SetString("2a")
    v.FieldByName("B").SetString("2b")
    v.FieldByName("C").SetString("2c")
    
    fmt.Println("After:   ", s)
    
    // Using a map:
    m := map[string]string{"A": "ma", "B": "mb", "C": "mc"}
    for mk, mv := range m {
        v.FieldByName(mk).SetString(mv)
    }
    
    fmt.Println("From Map:", s)
    

    Output:

    Before:   {a1 b2 c3}
    After:    {2a 2b 2c}
    From Map: {ma mb mc}
    

    I recommend to read this blog post to learn the basics of the reflection in Go:

    The Laws of Reflection

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 微信小程序协议怎么写
  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看