为什么我不能使用反射来获取切片的地址? [英] why can't I use reflection to take the address of a slice?
问题描述
slice:= make([] string,0,10)
sliceptr :=& slice
sliceptr:=& [] string {foo,bar,baz}
但这不是:
sliceaddrval:= reflect.ValueOf([]字符串{foo,bar,baz})。Addr()
与: reflect.Value.Addr of unaddressable value
编辑:总的来说,我试图做的是采取一个未知类型的结构,做一个该类型的结构片,并返回一个指针(我使用github.com/jmoiron/modl需要一个指针以分片填充来自SQL查询的结果)。
reflect.Value
将一个界面{}
和一个界面{}
设置为一个值,不能用于更改原本的。否则,如果您甚至不打算将指针传递给 struct
,那么您最终可能会更改代码。 (或者,在这种情况下,改变按值传递的片段的长度。)因此,如果您输入地址,您必须在 ValueOf
之前执行此操作。
制作一个指向切片的指针,您可以将它传递给一个包含的附加
的包(比如 modl
或Google App Engine GetMulti
),您可以使用类似 http://play.golang.org/p/1ZXsqjrqa3 ,复制于此:
$ b $ row struct {i,j int}
func main(){
Row:= row {}
$ b valueType:= reflect.ValueOf(aRow).Type ()
slicePtrVal:= reflect.New(reflect.SliceOf(valueType))
slicePtrIface:= slicePtrVal.Interface()
getQueryResults(slicePtrIface)
fmt。 println(slicePtrIface)
}
//代表`modl`或其他填充切片
func getQueryResults(slicePtr interface {}){
sPtr:= (* [] row)
(* sPtr)= append((* sPtr),row {1,3})
}
pre>
添加到 reflect.Value
中的切片时,您自己需要再加几行反映
,但听起来你正在使用的软件包会为你处理该部分。对于一般信息,执行附加操作的代码位于 http://play.golang.org/p/ m3-xFYc6ON 和以下:
package main
import(
fmt
反映
)
行结构{i,j int}
func main(){
aRow := row {}
//创建一个指向空片的指针
rowType:= reflect.ValueOf(aRow).Type()
slicePtrVal:= reflect.New reflect.SliceOf(rowType))
slicePtrIface:= slicePtrVal.Interface()
//追加零行
rowVal:= reflect.Zero(rowType)
sliceVal:= reflect.Indirect(slicePtrVal)
sliceVal.Set(reflect.Append(sliceVal,rowVal))
fmt.Println(slicePtrIface)
}
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).
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)
}
这篇关于为什么我不能使用反射来获取切片的地址?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!