小编典典

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

go

如何运作:

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查询结果填充的切片的指针)。


阅读 216

收藏
2020-07-02

共1个答案

小编典典

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

要指向可以传递给切片的包的指针append(例如modlGoogle 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)
}
2020-07-02