如何使用 "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
}

工作示例:https://play.golang.org/p/VE751GtSGEw