在golang中,使用reflect,如何设置struct字段的值?

前端之家收集整理的这篇文章主要介绍了在golang中,使用reflect,如何设置struct字段的值?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
有一个粗略的时间使用结构字段使用反射包。特别是,还没有弄清楚如何设置字段值。
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 fmtjson包。软件包文档具有指向软件包文件标题下的源代码文件链接

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

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

Go reflect软件包具有CanAddr功能

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.

Go reflect软件包有一个CanSet函数,如果为真,意味着CanAddr也是true。

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)
}

猜你在找的Go相关文章