1

尝试使用“反射”包设置接口值时遇到了困难。接口值实际上是在结构的结构内。在Go Playground中查看我的代码

基本上,在里面initProc,我想将dummyAFunc函数分配给struct中的DummyA字段Box

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 新手,我已经阅读了反射定律,但仍然无法弄清楚。请帮忙。谢谢!

4

1 回答 1

1

你正在传递一个**SmartBixto initProc。因此,当您使用反射取消引用一次时,Elem()您仍然会得到一个指针 ( *Smart box)。

由于new已经返回一个指针,只需使用:

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

于 2021-05-02T02:31:49.723 回答