[英]How I can update struct's array field value via reflect in Go?
I want to edit struct fields' value as interface{} parameters.我想将 struct 字段的值编辑为 interface{} 参数。 I done almost, but when struct has array field, I couldn't modify that.
我几乎完成了,但是当 struct 具有数组字段时,我无法修改它。 I tried to find proper function with array value, but I couldn't find that.
我试图用数组值找到合适的函数,但我找不到。 Here is my code.
这是我的代码。
edit_struct_via _interface.go edit_struct_via _interface.go
package main
import (
"reflect"
"fmt"
)
type myStruct struct {
Name [8]byte
TID [4]byte
Chksum uint16
}
func main() {
var s = new(myStruct)
name := []byte("Mike")
tid := []byte{0x01, 0x02, 0x03, 0x05}
setArrayField(name, s.Name[:])
setArrayField(tid, s.TID[:])
s.Chksum = 0x0101
myObj := reflect.ValueOf(s).Elem()
typeOfMyObj := myObj.Type()
for i := 0; i < myObj.NumField(); i++ {
f := myObj.Field(i)
fmt.Printf("%d: %s %s = %v\n", i,
typeOfMyObj.Field(i).Name, f.Type(), f.Interface())
}
newName := []byte("Emil")
myObj.Field(0).SetBytes(newName[:])
// I trying to change array field at here, but panic occur here.
// Because SetBytes must been called on slice, but myObj.Field(0) is array.
myObj.Field(2).SetUint(99) // It works.
fmt.Println("s is now: ", *s)
}
func setArrayField(src []byte, target []byte) {
// retun if src is bigger than target
if len(src) > len(target){
return
}
for index, item := range src {
target[index] = item
}
}
When I run above code, I get当我运行上面的代码时,我得到
0: Name [8]uint8 = [77 105 107 101 0 0 0 0]
1: TID [4]uint8 = [1 2 3 5]
2: Chksum uint16 = 257
panic: reflect: call of reflect.Value.SetBytes on array Value
goroutine 1 [running]:
reflect.flag.mustBe(...)
/usr/local/go/src/reflect/value.go:208
reflect.Value.SetBytes(0x4a6180, 0xc000098010, 0x191, 0xc000098078, 0x4, 0x4)
/usr/local/go/src/reflect/value.go:1557 +0x140
main.main()
/home/hornet/go/src/gateway-golang/edit_struct_via _interface.go:33 +0x522
exit status 2
I'm using Ubuntu 18.04 and go1.13 linux/amd64我使用的是 Ubuntu 18.04 和 go1.13 linux/amd64
The documentation for SetBytes says: SetBytes的文档说:
SetBytes sets v's underlying value.
SetBytes 设置 v 的基础值。 It panics if v's underlying value is not a slice of bytes.
如果 v 的基础值不是一个字节片,它会发生恐慌。
The underling value is an array as stated in the panic messge.底层值是恐慌消息中所述的数组。
Fix by copying the bytes to the array:通过将字节复制到数组来修复:
reflect.Copy(myObj.Field(0), reflect.ValueOf(newName))
SetBytes
works on slices. SetBytes
适用于切片。 Name
is not a slice, it is an array [8]byte
. Name
不是切片,它是一个数组[8]byte
。
There are important differences between slices and arrays, and you can't really use one for the other.切片和数组之间存在重要差异,您不能真正将其用于另一个。 A slice has a reference to an array, when you pass slices around, you pass the reference to the backing array.
切片具有对数组的引用,当您传递切片时,会将引用传递给后备数组。 An array is like a struct, when you pass an array to functions, you pass copies of that array, not a reference to it.
数组就像一个结构体,当您将数组传递给函数时,您传递的是该数组的副本,而不是对它的引用。
You can use reflect.Copy to copy bytes:您可以使用 reflect.Copy 来复制字节:
reflect.Copy(myObj.Field(0), reflect.ValueOf(newName))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.