【问题标题】:why can't I use reflection to take the address of a slice?为什么我不能使用反射来获取切片的地址?
【发布时间】:2014-11-05 18:56:48
【问题描述】:

这是怎么回事:

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

这也是:

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

但这不是:

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

它会恐慌:reflect.Value.Addr of unaddressable value


编辑:总的来说,我要做的是获取一个未知类型的结构,制作该类型的结构切片并返回指向它的指针(我正在使用 github.com/jmoiron/modl这需要一个指向切片的指针来填充 SQL 查询的结果)。

【问题讨论】:

    标签: reflection go slice


    【解决方案1】:

    reflect.Value 采用interface{},而interface{} 的值不能用于更改原始值。否则,当您甚至不打算将指针传递给它时,您最终可能会在 struct 中更改代码数据。 (或者,在这种情况下,更改按值传递的切片的长度。)因此,如果您获取地址,则必须在ValueOf 之前执行此操作。

    要创建一个指向切片的指针,您可以将其传递给将 append 传递给它的包(例如 modl 或 Google App Engine GetMulti),您可以使用 http://play.golang.org/p/1ZXsqjrqa3 之类的东西,复制这里:

    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}) 
    }
    

    您自己在reflect.Value 中附加到一个切片需要另外几行reflect,但听起来您正在使用的包会为您处理这部分。有关一般信息,执行附加的代码位于http://play.golang.org/p/m3-xFYc6ON 及以下:

    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)
    }
    

    【讨论】:

    • 其实觉得正确答案大同小异(就是不能像指针一样使用持有值类型的interface{}),编辑
    • 好的。你所说的切片头是有道理的,我想我只是不明白当你这样做时指针所指向的内容:&[]string{} 或者更确切地说为什么似乎没有反映等效的东西。
    • 我在这个问题上加了一点。基本上我正在寻找的是“制作一个 X 类型的空切片(“其他人”提供的结构)并获取指向它的指针”,我需要它来从查询中收集结果。
    • 知道了——即将更新它,以免对它不起作用的原因撒谎:) 如果可以的话,然后更新如何达到更具体的目标。
    • 因此,即使您刚刚创建了切片,也很难通过.Addr 获取指针(如图),但New() 在这里提供了帮助。用代码更新。
    猜你喜欢
    • 2015-12-06
    • 2018-04-16
    • 1970-01-01
    • 2012-12-20
    • 2015-07-22
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 2014-07-14
    相关资源
    最近更新 更多