有一个粗略的时间使用结构字段使用反射包。特别是,还没有弄清楚如何设置字段值。

type t struct { fi int; fs string }
var r t = t{ 123,"jblow" }
var i64 int64 = 456

>获取字段名称i – 这似乎工作

var field = reflect.TypeOf(r).Field(i).Name
>获取字段i的值为a)interface {},b)int – 这似乎工作

var iface interface {} = reflect.ValueOf(r).Field(i).Interface()

var i int = int(reflect.ValueOf(r).Field(i).Int())
>字段i的设置值 – 尝试一个 – panic

reflect.ValueOf(r).Field(i).SetInt(i64)

panic:reflect.Value·SetInt使用未导出字段获得的值

假设它不喜欢字段名“id”和“name”,因此重命名为“Id”和“Name”

a)这个假设是正确的吗?

b)如果正确,认为没有必要,因为在同一个文件/包
>设置字段i的值 – 尝试两个(字段名称大写) – panic

reflect.ValueOf(r).Field(i).SetInt(465)

reflect.ValueOf(r).Field(i).SetInt(i64)

panic:reflect.Value·SetInt使用不可解析的值

下面的@peterSO的说明是彻底和高质量

四。这个工作:

reflect.ValueOf(& r).Elem()。Field(i).SetInt(i64)

他还记录字段名称必须是可导出的(以大写字母开头)

Go是可用的 open source code.一个好的反思的方法是看看核心Go开发者如何使用它。例如,Go fmt和 json包。软件包文档具有指向软件包文件标题下的源代码文件的链接。

Go json包将编组和解组JSON从和到Go结构。

这里是一个分步示例,设置结构字段的值,同时小心避免错误。

reflectCanAddr
func (v Value) CanAddr() bool

CanAddr returns true if the value’s
address can be obtained with Addr.
Such values are called addressable. A
value is addressable if it is an
element of a slice,an element of an
addressable array,a field of an
addressable struct,or the result of
dereferencing a pointer. If CanAddr
returns false,calling Addr will
panic.

reflectCanSet
func (v Value) CanSet() bool

CanSet returns true if the value of v
can be changed. A Value can be changed
only if it is addressable and was not
obtained by the use of unexported
struct fields. If CanSet returns
false,calling Set or any
type-specific setter (e.g.,SetBool,
SetInt64) will panic.

我们需要确保我们可以设置struct字段。例如,

package main

import (
    "fmt"
    "reflect"
)

func main() {
    type t struct {
        N int
    }
    var n = t{42}
    // N at start
    fmt.Println(n.N)
    // pointer to struct - addressable
    ps := reflect.ValueOf(&n)
    // struct
    s := ps.Elem()
    if s.Kind() == reflect.Struct {
        // exported field
        f := s.FieldByName("N")
        if f.IsValid() {
            // A Value can be changed only if it is 
            // addressable and was not obtained by 
            // the use of unexported struct fields.
            if f.CanSet() {
                // change value of N
                if f.Kind() == reflect.Int {
                    x := int64(7)
                    if !f.OverflowInt(x) {
                        f.SetInt(x)
                    }
                }
            }
        }
    }
    // N at end
    fmt.Println(n.N)
}

Output:
42
7

如果我们可以确定所有的错误检查都是不必要的,这个例子简化了,

package main

import (
    "fmt"
    "reflect"
)

func main() {
    type t struct {
        N int
    }
    var n = t{42}
    fmt.Println(n.N)
    reflect.ValueOf(&n).Elem().FieldByName("N").SetInt(7)
    fmt.Println(n.N)
}