关于 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进行解引用之类的操作,非常难理解。

我现在已经能理解上一篇文章中的黑魔法代码了^^

bannerAds