dsv768456 2014-08-19 13:26
浏览 187
已采纳

为什么Golang反射.MakeSlice返回不可寻址的值

check the Snippet below:

http://play.golang.org/p/xusdITxgT-

Why is this happening? Because one of my argument must be a slice address.

Maybe I did not made it clear for everyone.

collection.Find(bson.M{}).All(&result)

The above code is why I need a slice address.

the result variable here is what I need. Now usually I can do this

result := make([]SomeStruct, 10, 10)

But now the SomeStruct is dynamic and I need to create the slice by using reflect.MakeSlice, So

result := reflect.MakeSlice(reflect.SliceOf(SomeType))

And it errors on : result must be a slice address.

  • 写回答

2条回答 默认 最新

  • dongyaoxiu6244 2014-08-19 14:46
    关注

    How to get a pointer to a slice using reflection

    The simplest solution is probably to use reflect.New() to create the pointer (full example on play):

    my := &My{}
    
    // Create a slice to begin with
    myType := reflect.TypeOf(my)
    slice := reflect.MakeSlice(reflect.SliceOf(myType), 10, 10)
    
    // Create a pointer to a slice value and set it to the slice
    x := reflect.New(slice.Type())
    x.Elem().Set(slice)
    
    collection.Find(bson.M{}).All(x.Interface())
    

    Note the x.Interface() that was pointed out by other answers as well. This prevents that instead of the reflect.Value the actual value of x is passed to All().

    Why does reflect.MakeSlice return an un-addressable Value?

    A loose definition of addressability in Go is that you can take the address of something and are guaranteed that this address points to somewhere meaningful. If you allocate something on the stack in the body of a function, the address of the allocated value will, at some point in time, not be accessible anymore. Therefore, this value is not addressable. In most cases, Go moves local stack variables to the heap if they are returned or otherwise promoted to the outside, but at runtime this is not done. Therefore, CanAddr() returns only true when:

    A value is addressable if it is an element of a slice, an element of an addressable array, a field of an addressable struct, or the result of dereferencing a pointer.

    The stated types all have one thing in common: they guarantee that what they hold will be accessible from everywhere and point to a meaningful value in memory. You have neither a slice element, nor a pointer, nor any of the other mentioned things since you created a local slice using reflect.MakeSlice. The elements of said slice would be addressable though (since the slice's memory resides on the heap).

    Why a pointer to a slice?

    The main question for me in this case was, why does the API of mgo require a pointer to a slice for iter.All? After all, slices are reference types and for changes in the provided data set, no pointer is necessary. But then it occurred to me that most of the time the function appends to the slice. Appending leads to memory allocation, memory allocation leads to copying the old data to new memory, new memory means a new address which needs to be communicated to the caller.

    This behaviour is illustrated in this example on play. In essence:

    // Works. Uses available storage of the slice.
        resultv.Index(1).Set(a)
    
    // Executes but changes are lost:   
    //  reflect.Append(resultv, a)
    
    // Does not work: reflect.Value.Set using unaddressable value
    //  resultv.Set(reflect.Append(resultv, a))
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 Oracle触发器记录修改前后的字段值
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器