使用reflect,如何设置结构字段的值?

在使用reflect包处理结构字段时遇到了麻烦。特别是,还没有弄清楚如何设置字段值。

输入t struct {fi int; fs字符串}

var rt = t {123,“ jblow”}

var i64 int64 = 456

  1. 获取字段i的名称-这似乎起作用

var field = reflect.TypeOf(r).Field(i).Name

  1. 作为a)接口{},b)int获取字段i的值-这似乎有效

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

var i int = int(reflect.ValueOf(r).Field(i).Int())

  1. 设置字段i的值-尝试一次-紧急

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

恐慌 :使用未导出字段中获得的值,使用reflect.Value·SetInt

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

a)这个假设正确吗?

b)如果正确,则认为没有必要,因为在同一文件/包中

  1. 设置字段i的值-尝试两个(字段名大写)-紧急

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

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

恐慌 :使用不可寻址的值反映。


@peterSO的以下说明全面,高质量

四。这有效:

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

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

回答:

Go是开放源代码。了解反射的一个好方法是查看核心Go开发人员如何使用它。例如,Go

fmt和json包。软件包文档在“软件包文件”标题下具有指向源代码文件的链接。

Go json程序包将JSON从Go结构中封送和解组。


这是一个分步示例,它struct在谨慎地避免错误的同时设置字段的值。

Go

reflect软件包具有一个CanAddr功能。

func (v Value) CanAddr() bool

如果可以通过Addr获取值的地址,则CanAddr返回true。这样的值称为可寻址的。如果值是切片的元素,可寻址数组的元素,可寻址结构的字段或取消引用指针的结果,则该值是可寻址的。如果CanAddr返回false,则调用Addr会惊慌。

Go

reflect程序包具有一个CanSet函数,如果有的话true,意味着它CanAddr也为true

func (v Value) CanSet() bool

如果v的值可以更改,则CanSet返回true。值只能是可寻址的,并且不是通过使用未导出的结构字段获得的,才可以更改。如果CanSet返回false,则调用Set或任何特定于类型的setter(例如SetBool,SetInt64)都会感到恐慌。

我们需要确保我们能做到Set这一点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)

}

以上是 使用reflect,如何设置结构字段的值? 的全部内容, 来源链接: utcz.com/qa/412348.html

回到顶部