dsy1971 2014-11-05 18:56
浏览 31
已采纳

为什么不能使用反射来获取切片的地址?

How come this works:

slice := make([]string, 0, 10)
sliceptr := &slice

this too:

sliceptr := &[]string{"foo","bar","baz"}

But this doesn't:

sliceaddrval := reflect.ValueOf([]string{"foo","bar","baz"}).Addr()

It panics with: reflect.Value.Addr of unaddressable value


EDIT: Overall what I'm trying to do is take a struct that is of an unknown type, make a slice of structs of that type and return a pointer to it (I'm using github.com/jmoiron/modl which requires a pointer to slice to populate with results from a SQL query).

  • 写回答

1条回答 默认 最新

  • duandi4238 2014-11-05 19:13
    关注

    reflect.Value takes an interface{}, and an interface{} to a value can't be used to change the original. Otherwise, you could end up with code changing data in your struct when you didn't even intend to pass it a pointer. (Or, in this case, changing the length of a slice that was passed by value.) So if you take the address you'd have to do it before the ValueOf.

    To make a pointer to a slice that you can to pass to a package that will append to it (like modl or Google App Engine GetMulti), you'd use something like http://play.golang.org/p/1ZXsqjrqa3, copied here:

    package main
    
    import (
        "fmt"
        "reflect"
    )
    
    type row struct { i, j int }
    
    func main() {
        aRow := row{}
    
        valueType := reflect.ValueOf(aRow).Type()
        slicePtrVal := reflect.New(reflect.SliceOf(valueType))
        slicePtrIface := slicePtrVal.Interface()
    
        getQueryResults(slicePtrIface)
        fmt.Println(slicePtrIface)
    }
    
    // standing in for `modl` or whatever populates the slice
    func getQueryResults(slicePtr interface{}) {
        sPtr := slicePtr.(*[]row)
        (*sPtr) = append((*sPtr), row{1,3}) 
    }
    

    Appending to a slice in a reflect.Value yourself takes another few lines of reflect, but it sounds like the package you're working with takes care of that part for you. For general info, code to do the append is at http://play.golang.org/p/m3-xFYc6ON and below:

    package main
    
    import (
        "fmt"
        "reflect"
    )
    
    type row struct { i, j int }
    
    func main() {
        aRow := row{}
    
        // make a pointer to an empty slice
        rowType := reflect.ValueOf(aRow).Type()
        slicePtrVal := reflect.New(reflect.SliceOf(rowType))
        slicePtrIface := slicePtrVal.Interface()
    
        // append a zero row to it
        rowVal := reflect.Zero(rowType)
        sliceVal := reflect.Indirect(slicePtrVal)
        sliceVal.Set(reflect.Append(sliceVal, rowVal))
    
        fmt.Println(slicePtrIface)
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 matlab有关常微分方程的问题求解决
  • ¥15 perl MISA分析p3_in脚本出错
  • ¥15 k8s部署jupyterlab,jupyterlab保存不了文件
  • ¥15 ubuntu虚拟机打包apk错误
  • ¥199 rust编程架构设计的方案 有偿
  • ¥15 回答4f系统的像差计算
  • ¥15 java如何提取出pdf里的文字?
  • ¥100 求三轴之间相互配合画圆以及直线的算法
  • ¥100 c语言,请帮蒟蒻写一个题的范例作参考
  • ¥15 名为“Product”的列已属于此 DataTable