以下のスニペットを確認してください。
http://play.golang.org/p/xusdITxgT-
なんでこんなことが起こっているの?私の議論の1つはスライスアドレスでなければならないからです。
多分私は皆のためにそれを明らかにしなかった。
collection.Find(bson.M{}).All(&result)
上記のコードは、スライスアドレスが必要な理由です。
ここでの結果変数は私が必要とするものです。今、私は通常これを行うことができます
result := make([]SomeStruct, 10, 10)
しかし、SomeStructは動的であり、reflect.MakeSliceを使用してスライスを作成する必要があります。
result := reflect.MakeSlice(reflect.SliceOf(SomeType))
そしてそれはエラーになります:結果はスライスアドレスでなければなりません。
最も簡単な解決策は、おそらくreflect.New()
を使用してポインターを作成することです( 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())
_
他の回答でも指摘されたx.Interface()
に注意してください。これにより、_reflect.Value
_の代わりにx
の実際の値がAll()
に渡されるのを防ぎます。
Goでの addressability の大まかな定義は、何かのアドレスを取得でき、このアドレスが意味のある場所を指していることが保証されるということです。関数の本体のスタックに何かを割り当てると、割り当てられた値のアドレスは、ある時点でアクセスできなくなります。したがって、この値はアドレス指定できません。ほとんどの場合、Goは、ローカルスタック変数が返されるか、外部にプロモートされると、ヒープに移動しますが、実行時にはこれは行われません。したがって、 CanAddr()
は、次の場合にtrue
のみを返します。
値がスライスの要素、アドレス指定可能な配列の要素、アドレス指定可能な構造体のフィールド、またはポインターの逆参照の結果である場合、値はアドレス指定可能です。
記載されているタイプにはすべて共通点が1つあります。それは、保持しているものがどこからでもアクセス可能であり、メモリ内の意味のある値を指すことを保証することです。 _reflect.MakeSlice
_を使用してローカルスライスを作成したため、スライスelement、ポインター、その他の言及されたものはありません。ただし、上記のスライスのelementsはアドレス指定可能です(スライスのメモリはヒープ上にあるため)。
この場合の私にとっての主な質問は、なぜ mgo のAPIが _iter.All
_ のスライスへのポインターを必要とするのかということでした。結局のところ、スライスは参照型であり、提供されたデータセットを変更する場合、ポインターは必要ありません。しかし、ほとんどの場合、関数 がスライスにを追加する ということに気づきました。追加するとメモリが割り当てられ、メモリの割り当てによって古いデータが新しいメモリにコピーされます。新しいメモリとは、呼び出し元に伝達する必要のある新しいアドレスを意味します。
この動作は この例はプレイ中 に示されています。本質的に:
_// 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))
_
ここでは interface()
メソッドを使用していると思いますが、reflect
を使用して型のスライスバックを作成する必要がある理由がわかりません。
package main
import (
"fmt"
"reflect"
)
type My struct {
Name string
Id int
}
func main() {
my := &My{}
myType := reflect.TypeOf(my)
slice := reflect.MakeSlice(reflect.SliceOf(myType), 10, 10).Interface()
p := slice.([]*My)
fmt.Printf("%T %d %d\n", p, len(p), cap(p))
}
生産:
[] * main.My 10 10