反射:在运行时,动态获取对象的类型和内存结构
反射操作所需要的全部信息都源自接口变量,接口变量除了存储自身类型外,还会保存实际对象的类型数据
将任何传入的对象转换为接口类型:
func TypeOf(o interface{}) Type func ValueOf(o interface{}) Value反射可以将 “接口类型变量” 转换为 “反射类型对象” (Reflection goes from interface value to reflection object.)
反射可以将 “反射类型对象” 转换为 “接口类型变量” (Reflection goes from reflection object to interface value.)
如果要修改 “反射类型对象” 其类型必须是 可写的 (To modify a reflection object, the value must be settable.)
“接口变量” => “反射对象”
reflect.TypeOf(i): 获取接口值的类型 (*reflect.rtype)reflect.ValueOf(i): 获取接口值的值 (reflect.Value)“反射对象” => “接口变量”
注意:只有Value才能逆向转换,Type则不行
func (v Value) Interface() (i interface{}) { return valueInterface(v, true) }第一和第二定律综合:
要修改反射对象,其值必须可写的。
非指针变量创建的反射对象,不可写CanSet()返回true,为可写对象不可写对象,无法进行写操作可写对象,使用Elem()函数返回指针指向的数据 func main() { s := "abc" v1 := reflect.ValueOf(s) fmt.Println(v1.CanSet()) // false v2 := reflect.ValueOf(&s) fmt.Println(v2.CanSet()) // false v3 := v2.Elem() // 只有引用类型,才有Elem()方法 fmt.Println(v3.CanSet()) // true }可写对象的相关方法:
Set(x Value) SetBool(x bool) SetBytes(x []byte) setRunes(x []rune) SetComplex(x complex128) SetFloat(x float64) SetInt(x int64) SetLen(n int) SetCap(n int) SetMapIndex(key Value, elem Value) SetUint(x uint64) SetPointer(x unsafe.Pointer) SetString(x string)reflect.Type: 以接口的形式存在
type Type interface { Align() int FieldAlign() int Method(int) Method MethodByName(string) (Method, bool) NumMethod() int Name() string PkgPath() string Size() uintptr String() string Kind() Kind Implements(u Type) bool AssignableTo(u Type) bool ConvertibleTo(u Type) bool Comparable() bool Bits() int ChanDir() ChanDir IsVariadic() bool Elem() Type Field(i int) StructField FieldByIndex(index []int) StructField FieldByName(name string) (StructField, bool) FieldByNameFunc(match func(string) bool) (StructField, bool) In(i int) Type Key() Type Len() int NumField() int NumIn() int NumOut() int Out(i int) Type common() *rtype uncommon() *uncommonType }返回引用类型 (指针、数组、切片、字典值 或 通道) 的基类型
func main() { a := [...]byte{1, 2, 3} s := []int{1, 2, 3} m := make(map[int]string) c := make(chan bool) ta := reflect.TypeOf(a) ts := reflect.TypeOf(s) tm := reflect.TypeOf(m) tc := reflect.TypeOf(c) fmt.Println(ta, ta.Elem()) // [3]uint8 uint8 fmt.Println(ts, ts.Elem()) // []int int fmt.Println(tm, tm.Elem()) // map[int]string string fmt.Println(tc, tc.Elem()) // chan bool bool }Implements(), ConvertibleTo(), AssignableTo()
func main() { type X int var a X t := reflect.TypeOf(a) fmt.Println(t) // main.X ts := reflect.TypeOf((*fmt.Stringer)(nil)).Elem() fmt.Println(ts) // fmt.Stringer ti := reflect.TypeOf(10) fmt.Println(ti) // int fmt.Println(t.Implements(ts)) // false //fmt.Println(t.Implements(ti)) // panic: reflect: non-interface type passed to Type.Implements fmt.Println(t.ConvertibleTo(ts)) // false fmt.Println(t.ConvertibleTo(ti)) // true fmt.Println(t.AssignableTo(ts)) // false fmt.Println(t.AssignableTo(ti)) // false }获取结构体内容: Field(), FieldByIndex(), FieldByName(), FieldByNameFunc()
type StructField struct { Name string PkgPath string Type Type // field type Tag StructTag // field tag string Offset uintptr // offset within struct, in bytes Index []int // index sequence for Type.FieldByIndex Anonymous bool // is an embedded field } func main() { user := struct { Name string `json:"name"` Age byte `json:"age"` }{"daniel", 21} t := reflect.TypeOf(user) for i := 0; i < t.NumField(); i++ { tf := t.Field(i) fmt.Println(tf.Name, tf.Type, tf.Tag) // Name string json:"name" } if tf, ok := t.FieldByName("Age"); ok { fmt.Println(tf.Type, tf.Tag.Get("json")) // uint8 age } }reflect.Value: 以结构体形式存在
type Value struct { typ *rtype ptr unsafe.Pointer flag } func (v Value) Addr() Value func (v Value) Bool() bool func (v Value) Bytes() []byte func (v Value) Call(in []Value) []Value func (v Value) CallSlice(in []Value) []Value func (v Value) CanAddr() bool func (v Value) CanInterface() bool func (v Value) CanSet() bool func (v Value) Cap() int func (v Value) Close() func (v Value) Complex() complex128 func (v Value) Convert(t Type) Value func (v Value) Elem() Value func (v Value) Field(i int) Value func (v Value) FieldByIndex(index []int) Value func (v Value) FieldByName(name string) Value func (v Value) FieldByNameFunc(match func(string) bool) Value func (v Value) Float() float64 func (v Value) Index(i int) Value func (v Value) Int() int64 func (v Value) Interface() (i interface}) func (v Value) InterfaceData() [2]uintptr func (v Value) IsNil() bool func (v Value) IsValid() bool func (v Value) IsZero() bool func (v Value) Kind() Kind func (v Value) Len() int func (v Value) MapIndex(key Value) Value func (v Value) MapKeys() []Value func (v Value) MapRange() *MapIter func (v Value) Method(i int) Value func (v Value) MethodByName(name string) Value func (v Value) NumField() int func (v Value) NumMethod() int func (v Value) OverflowComplex(x complex128) bool func (v Value) OverflowFloat(x float64) bool func (v Value) OverflowInt(x int64) bool func (v Value) OverflowUint(x uint64) bool func (v Value) Pointer() uintptr func (v Value) Recv() (x Value, ok bool) func (v Value) Send(x Value) func (v Value) Set(x Value) func (v Value) SetBool(x bool) func (v Value) SetBytes(x []byte) func (v Value) SetCap(n int) func (v Value) SetComplex(x complex128) func (v Value) SetFloat(x float64) func (v Value) SetInt(x int64) func (v Value) SetLen(n int) func (v Value) SetMapIndex(key, elem Value) func (v Value) SetPointer(x unsafe.Pointer) func (v Value) SetString(x string) func (v Value) SetUint(x uint64) func (v Value) Slice(i, j int) Value func (v Value) Slice3(i, j, k int) Value func (v Value) String() string func (v Value) TryRecv() (x Value, ok bool) func (v Value) TrySend(x Value) bool func (v Value) Type() Type func (v Value) Uint() uint64 func (v Value) UnsafeAddr() uintptr func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value func (v Value) call(op string, in []Value) []Value func (v Value) pointer() unsafe.Pointer func (v Value) recv(nb bool) (val Value, ok bool) func (v Value) runes() []rune func (v Value) send(x Value, nb bool) (selected bool) func (v Value) setRunes(x []rune)接口变量会复制对象,是unaddressable的;要想修改目标对象,必须使用指针;传入的值必选是pointer-interface
func main() { x := 10 v1 := reflect.ValueOf(x) fmt.Println(v1.CanAddr(), v1.CanSet()) // false, false fmt.Println(v1.Kind() == reflect.Ptr) // false v2 := reflect.ValueOf(&x) fmt.Println(v2.CanAddr(), v2.CanSet()) // false, false fmt.Println(v2.Kind() == reflect.Ptr) // true fmt.Println(v2.Elem().CanAddr(), v2.Elem().CanSet()) // true, true v2.Elem().SetInt(5) fmt.Println(x) // 5 }反射匿名或嵌入字段:匿名字段当独立字段处理
type User struct { Id int Name string Age byte } type Manager struct { User Title string } func main() { m := Manager{User: User{1, "Jack", 21}, Title: "CEO"} t := reflect.TypeOf(m) fmt.Printf("%#v\n", t.Field(0)) // {Name:"User", ..., Anonymous:true} fmt.Printf("%#v\n", t.Field(1)) // {Name:"Title", ..., Anonymous:false} fmt.Printf("%#v\n", t.FieldByIndex([]int{0})) // Same as t.Field(0),{Name:"User", ..., Anonymous:true} fmt.Printf("%#v\n", t.FieldByIndex([]int{0, 1})) // {Name:"Name", ..., Anonymous:false} field, ok := t.FieldByName("Title") if ok { fmt.Printf("%#v\n", field) // {Name:"Title", ..., Anonymous:false} } field, ok = t.FieldByName("Id") if ok { fmt.Printf("%#v\n", field) // {Name:"Id", ..., Anonymous:false} } }反射库提供了内置函数 make() 和 new() 的对应操作,例如 MakeFunc()。可用它实现通用模板,适应不同数据类型。
func main() { var intAdd func(x, y int) int var strAdd func(x, y string) string makeAdd(&intAdd) makeAdd(&strAdd) fmt.Println(intAdd(8, 9)) fmt.Println(strAdd("Hi", "sara")) } func makeAdd(o interface{}) { fn := reflect.ValueOf(o).Elem() v := reflect.MakeFunc(fn.Type(), add) fn.Set(v) } func add(args []reflect.Value) (results []reflect.Value) { if len(args) == 0 { return nil } var ret reflect.Value switch args[0].Kind() { case reflect.Int: sum := 0 for _, n := range args { sum += int(n.Int()) } ret = reflect.ValueOf(sum) case reflect.String: ss := make([]string, 0, len(args)) for _, s := range args { ss = append(ss, s.String()) } ret = reflect.ValueOf(strings.Join(ss, " ")) } results = append(results, ret) return }