关于 Golang 切片的反射
package main
import (
"fmt"
"reflect"
)
// 基本型(Bool, String, すべての数値)
// 合成型(Struct, Array)
// 参照型(Chan, Func, Ptr, Slice, Map, Interface{})
// その他(reflect.Valueのゼロ値, 全く値ではないという意味の Invalid)
// .Elem()は、ポインタ型のとき実体を返す。また、ポインタ型のreflect.valueのみ、値をセットできる。
// .Interface()は、interfece{}の値を返します。
func main() {
type Foo struct {
Name string `json:"name" bson:"name"`
}
arr := []Foo{} // 空のスライスを作成
arr = append(arr, Foo{Name: "aaa"}) // 空のスライスに構造体を1個追加
// ------------------------------ ここまで普通。
// リフレクション型の状態で操作できるようにポインタを渡す。
// この時点でデリファレンスしているため、最後に戻すときにはデリファレンスは必要ない。
s := reflect.ValueOf(&arr).Elem()
fmt.Println(s.CanAddr(), s.CanSet()) // true true
rv := reflect.New(reflect.TypeOf(Foo{})) // reflect.Newの場合は、ポインタ型で作成される、最初から辿れるしセットもできる
fmt.Println(rv) // &{}
rve := rv.Elem() // {} デリファレンス
fmt.Println(rv.CanAddr(), rv.CanSet()) // true true
// rve.Field(0).SetString("eee") // OK
// rve.Field(0).Set(reflect.ValueOf("eee")) // OK
rve.FieldByName("Name").SetString("bbb")
s.Set(reflect.Append(s, rve)) // OK
s.Set(reflect.Append(s, reflect.ValueOf(&Foo{Name: "ccc"}).Elem())) // OK
// リフレクション型からinterface{}型にして、型アサーションで元の型に戻す
px := s.Interface().([]Foo)
fmt.Println(px)
}
按照写的那样,但是用.Elem进行解引用之类的操作,非常难理解。
我现在已经能理解上一篇文章中的黑魔法代码了^^