2 回答
TA贡献1772条经验 获得超8个赞
正如错误call of reflect.flag.mustBeAssignable on zero Value所说,newTValue.Elem().FieldByName(newTTag).CanSet()在您的代码中并根据文档返回 false
Set 将 x 分配给值 v。如果 CanSet 返回 false,它会发生混乱。与 Go 一样,x 的值必须可分配给 v 的类型。
这是更正的代码,它从一个对象中获取字段并将值分配给另一个对象。
package main
import (
"fmt"
"reflect"
)
type T struct {
A int `json:"aaa" test:"AA"`
B string `json:"bbb" test:"BB"`
}
type newT struct {
AA int
BB string
Testaaa string
}
func main() {
t := T{
A: 123,
B: "hello",
}
tt := reflect.TypeOf(t)
tv := reflect.ValueOf(t)
newT := &newT{}
newTValue := reflect.ValueOf(newT)
for i := 0; i < tt.NumField(); i++ {
field := tt.Field(i)
newTTag := field.Tag.Get("test")
tValue := tv.Field(i)
newTfield := newTValue.Elem().FieldByName(newTTag)
if newTfield.CanSet() {
newTfield.Set(tValue)
}
}
fmt.Println(newT)
}
TA贡献1803条经验 获得超6个赞
第一的:
for i := 0; i < tt.NumField(); i++ {
field := tt.Field(i)
这里的每一步都会遍历 type 实例的字段T。因此,这些字段将是A——或者更确切地说,是字段描述符,它的NameisA和它描述了一个带有 json 和 test 标记的 int ——然后B(如果我们再进一步,具有相同的挑剔细节)。
由于两个字段描述符只有两个Get-able 项目,因此您可能打算使用Get("test"),如Guarav Dhiman 的回答。
但是,如果你这样做,结果是"testaaa"你在场上A和"testbbb"场上的时候B。如果我们对 Guarav 的代码多加注解:
for i := 0; i < tt.NumField(); i++ {
field := tt.Field(i)
newTTag := field.Tag.Get("test")
fmt.Printf("newTTag = %#v\n", newTTag)
tValue := tv.Field(i)
newTfield := newTValue.Elem().FieldByName(newTTag)
fmt.Printf("newTfield = %#v\n", newTfield)
if newTfield.CanSet() {
newTfield.Set(tValue)
}
}
我们将看到这个输出:
newTTag = "testaaa"
newTfield = <invalid reflect.Value>
newTTag = "testbbb"
newTfield = <invalid reflect.Value>
我们需要的是使test每个标签名称中的字符串成为类型中的字段newT:
type T struct {
A int `json:"aaa" test:"AA"`
B string `json:"bbb" test:"BB"`
}
(Guarav 实际上已经这样做了,但没有提及。)现在程序产生了(大概)你想要的:
&{123 hello}
- 2 回答
- 0 关注
- 226 浏览
添加回答
举报