![](/img/trans.png)
[英]Err: reflect.flag.mustBeAssignable using unaddressable value as I try to use BindQuery method
[英]reflect runtime error: call of reflect.flag.mustBeAssignable on zero Value
我正在 go playground 上測試這個代碼片段,我的目標是使用反射從一個對象中獲取字段,然后將值設置為另一個對象
package main
import (
"fmt"
"reflect"
)
type T struct {
A int `json:"aaa" test:"testaaa"`
B string `json:"bbb" test:"testbbb"`
}
type newT struct {
AA int
BB 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("newT")
tValue := tv.Field(i)
newTValue.Elem().FieldByName(newTTag).Set(tValue)
}
fmt.Println(newT)
}
它給出了一個非常奇怪的錯誤:
panic: reflect: call of reflect.flag.mustBeAssignable on zero Value
goroutine 1 [running]:
reflect.flag.mustBeAssignableSlow(0x0, 0x0)
/usr/local/go/src/reflect/value.go:240 +0xe0
reflect.flag.mustBeAssignable(...)
/usr/local/go/src/reflect/value.go:234
reflect.Value.Set(0x0, 0x0, 0x0, 0x100f80, 0x40a0f0, 0x82)
/usr/local/go/src/reflect/value.go:1531 +0x40
main.main()
/tmp/sandbox166479609/prog.go:32 +0x400
Program exited: status 2.
如何解決?
這是作為call of reflect.flag.mustBeAssignable on zero Value
錯誤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)
}
第一的:
for i := 0; i < tt.NumField(); i++ {
field := tt.Field(i)
這里的每一步都遍歷T
類型實例的字段。 所以字段將是A
-或者更確切地說,現場描述,其Name
為A
,並描述其JSON和測試代碼,然后一個int B
(具有相同的挑剔細節,如果我們再往前走)。
由於兩個字段描述符都只有兩個Get
able 項,因此您可能打算使用Get("test")
,如Guarav Dhiman 的 answer 。
如果你這樣做,不過,結果是"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"`
}
(瓜拉夫實際上已經這樣做了,但沒有提到它。)現在程序產生了(大概)你想要的:
&{123 hello}
帶有注釋掉跟蹤的完整程序在這里。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.