duanpingzu7194 2017-07-16 23:14
浏览 147
已采纳

如何使用反射将值设置为包含nil的指针

I'm trying to set a value to a nil pointer in a struct like so.

// https://play.golang.org/p/jPTMNC_ZQ9
package main

import (
    "fmt"
    "reflect"
)

type T struct {
    A *int
}

func main() {
    fmt.Println("Hello, playground")
    t := &T{}

    v := 1
    vptr := &v

    CopyValue(vptr, t.A) // I want to set t.A to contain 1
}

func CopyValue(src interface{}, dest interface{}) {
    srcRef := reflect.ValueOf(src)
    if srcRef.Kind() == reflect.Ptr {
        srcRef = srcRef.Elem()
    }

    destRef := reflect.New(srcRef.Type()).Elem()
    destRef.Set(srcRef)
    reflect.ValueOf(dest).Elem().Set(destRef)
}

However, I encounter the following error:

panic: reflect: call of reflect.Value.Set on zero Value

goroutine 1 [running]:
reflect.flag.mustBeAssignable(0x0, 0x1040a128)
    /usr/local/go/src/reflect/value.go:221 +0x260
reflect.Value.Set(0x0, 0x0, 0x0, 0xdefc0, 0x1040a128, 0x182)
    /usr/local/go/src/reflect/value.go:1339 +0x40
main.CopyValue(0xd7860, 0x1040a124, 0xd7860, 0x0)
    /tmp/sandbox487854080/main.go:30 +0x1a0
main.main()
    /tmp/sandbox487854080/main.go:19 +0x100

What am I doing wrong?

  • 写回答

3条回答 默认 最新

  • doujiao1814 2017-07-17 03:06
    关注

    In order to be able to modify what t.A points to, you need to send a reference to it to your CopyValue function.

    CopyValue(vptr, &t.A) // (note the &)
    

    You can then assign the pointer to the new address:

    func CopyValue(src interface{}, dest interface{}) {
        srcRef := reflect.ValueOf(src)
        vp := reflect.ValueOf(dest)
        vp.Elem().Set(srcRef)
    }
    

    See the 3rd "law of reflection" here: https://blog.golang.org/laws-of-reflection

    Full working code:

    package main
    
    import (
        "fmt"
        "reflect"
    )
    
    type T struct {
        A *int
    }
    
    func main() {
        t := &T{}
        v := 1
        vptr := &v
        CopyValue(vptr, &t.A) // we pass a reference to t.A since we want to modify it
        fmt.Printf("%v
    ", *t.A)
    }
    
    func CopyValue(src interface{}, dest interface{}) {
        srcRef := reflect.ValueOf(src)
        vp := reflect.ValueOf(dest)
        vp.Elem().Set(srcRef)
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 微信小程序协议怎么写
  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看