如何使用 "reflect" 在结构的结构中设置接口值
How to use "reflect" to set interface value inside a struct of struct
尝试使用“reflect”包设置接口值时遇到了困难。接口值实际上在结构的结构中。在 Go Playground
中查看我的代码
基本上,在 initProc
中,我想将 dummyAFunc
函数分配给 Box
struct
中的 DummyA
字段
package main
import (
"fmt"
"reflect"
)
type Box struct {
Name string
DummyA interface{}
}
type SmartBox struct {
Box
}
func dummyAFunc(i int) {
fmt.Println("dummyAFunc() is here!")
}
func initProc(inout interface{}) {
// Using "inout interface{}", I can take any struct that contains Box struct
// And my goal is assign dummyAFunc to dummyA in Box struct
iType:=reflect.TypeOf(inout)
iValue:=reflect.ValueOf(inout)
fmt.Println("Type & value:", iType.Elem(), iValue.Elem()) // Type & value: *main.SmartBox &{{ <nil>}}
e := reflect.ValueOf(inout).Elem()
fmt.Println("Can set?", e.CanSet()). // true
fmt.Println("NumField", e.NumField()) // panic: reflect: call of reflect.Value.NumField on ptr Value ?????
fmt.Println("NumMethod", e.NumMethod()) // NumMethod = 0
}
func main() {
smartbox := new (SmartBox)
initProc(&smartbox)
}
我是 Go 的新手,我已经阅读了 The laws of Reflection 但仍然无法理解。请帮忙。谢谢!
您正在将 **SmartBix
传递给 initProc
。因此,当您使用反射的 Elem()
取消引用一次时,您仍然会得到一个指针 (*Smart box
).
由于new
已经returns一个指针,只需使用:
smartbox := new (SmartBox)
// InitProc(smartbox) // **SmartBox
InitProc(smartbox) // *SmartBox
https://play.golang.org/p/j4q6aq6QL_4
编辑
要更新输入结构的 DummyA
字段,您可以这样做:
func initProc2(v interface{}) error {
if reflect.TypeOf(v).Kind() != reflect.Ptr {
return fmt.Errorf("value must be a pointer")
}
dv := reflect.ValueOf(v).Elem()
if dv.Kind() != reflect.Struct {
return fmt.Errorf("value must be a pointer to a struct/interface")
}
const fname = "DummyA" // lookup field name
f := dv.FieldByName(fname)
if !f.CanSet() {
return fmt.Errorf("value has no field %q or cannot be set", fname)
}
nv := reflect.ValueOf(dummyAFunc)
f.Set(nv)
return nil
}
尝试使用“reflect”包设置接口值时遇到了困难。接口值实际上在结构的结构中。在 Go Playground
中查看我的代码基本上,在 initProc
中,我想将 dummyAFunc
函数分配给 Box
struct
DummyA
字段
package main
import (
"fmt"
"reflect"
)
type Box struct {
Name string
DummyA interface{}
}
type SmartBox struct {
Box
}
func dummyAFunc(i int) {
fmt.Println("dummyAFunc() is here!")
}
func initProc(inout interface{}) {
// Using "inout interface{}", I can take any struct that contains Box struct
// And my goal is assign dummyAFunc to dummyA in Box struct
iType:=reflect.TypeOf(inout)
iValue:=reflect.ValueOf(inout)
fmt.Println("Type & value:", iType.Elem(), iValue.Elem()) // Type & value: *main.SmartBox &{{ <nil>}}
e := reflect.ValueOf(inout).Elem()
fmt.Println("Can set?", e.CanSet()). // true
fmt.Println("NumField", e.NumField()) // panic: reflect: call of reflect.Value.NumField on ptr Value ?????
fmt.Println("NumMethod", e.NumMethod()) // NumMethod = 0
}
func main() {
smartbox := new (SmartBox)
initProc(&smartbox)
}
我是 Go 的新手,我已经阅读了 The laws of Reflection 但仍然无法理解。请帮忙。谢谢!
您正在将 **SmartBix
传递给 initProc
。因此,当您使用反射的 Elem()
取消引用一次时,您仍然会得到一个指针 (*Smart box
).
由于new
已经returns一个指针,只需使用:
smartbox := new (SmartBox)
// InitProc(smartbox) // **SmartBox
InitProc(smartbox) // *SmartBox
https://play.golang.org/p/j4q6aq6QL_4
编辑
要更新输入结构的 DummyA
字段,您可以这样做:
func initProc2(v interface{}) error {
if reflect.TypeOf(v).Kind() != reflect.Ptr {
return fmt.Errorf("value must be a pointer")
}
dv := reflect.ValueOf(v).Elem()
if dv.Kind() != reflect.Struct {
return fmt.Errorf("value must be a pointer to a struct/interface")
}
const fname = "DummyA" // lookup field name
f := dv.FieldByName(fname)
if !f.CanSet() {
return fmt.Errorf("value has no field %q or cannot be set", fname)
}
nv := reflect.ValueOf(dummyAFunc)
f.Set(nv)
return nil
}