反射是程序在运行期间获取变量的类型和值、或者执行变量的方法的能力。Golang反射包中有两对非常重要的函数和类型,两个函数分别是:
. reflect.TypeOf能获取类型信息reflect.Type;
. reflect.ValueOf 能获取数据的运行时表示reflect.Value;func main() { type MyInt32 int32 a := MyInt32(1) b := int32(1) fmt.Printf("reflect.TypeOf(a):%v Kind:%v\n", reflect.TypeOf(a), reflect.TypeOf(a).Kind()) fmt.Printf("reflect.TypeOf(b):%v Kind:%v\n", reflect.TypeOf(b), reflect.TypeOf(b).Kind()) }代码输出如下,由此可以看出int32、type MyInt32 int32是两种不同类型,但都属于int32这个种类。
$ go run main.go reflect.TypeOf(a):main.MyInt32 Kind:int32 reflect.TypeOf(b):int32 Kind:int32种类定义
// A Kind represents the specific kind of type that a Type represents. // The zero Kind is not a valid kind. type Kind uint const ( Invalid Kind = iota Bool Int Int8 Int16 Int32 Int64 Uint Uint8 Uint16 Uint32 Uint64 Uintptr Float32 Float64 Complex64 Complex128 Array Chan Func Interface Map Pointer Slice String Struct UnsafePointer )2.2 引用指向元素的类型
func main() { type myStruct struct { } a := &myStruct{} typeA := reflect.TypeOf(a) fmt.Printf("TypeOf(a):%v Kind:%v\n", typeA, typeA.Kind()) fmt.Printf("TypeOf(a).Elem():%v Elem().Kind:%v\n", typeA.Elem(), typeA.Elem().Kind()) s := []int64{} typeS := reflect.TypeOf(s) fmt.Printf("TypeOf(s):%v Kind:%v\n", typeS, typeS.Kind()) fmt.Printf("TypeOf(s).Elem():%v Elem().Kind:%v\n", typeS.Elem(), typeS.Elem().Kind()) }代码输出如下,由此可以看出,通过reflect.Elem()函数可以获取引用指向数据的类型。
$ go run main.go TypeOf(a):*main.myStruct Kind:ptr TypeOf(a).Elem():main.myStruct Elem().Kind:struct TypeOf(s):[]int64 Kind:slice TypeOf(s).Elem():int64 Elem().Kind:int642.3 结构体成员类型
func main() { type secStruct struct { Cnt []int64 } type myStruct struct { Num int `json:"num_json" orm:"column:num_orm"` Desc string `json:"desc_json" orm:"column:desc_orm"` Child secStruct } s := myStruct{} typeS := reflect.TypeOf(s) // 成员数量 fmt.Printf("NumField:%v \n", typeS.NumField()) // 每个成员的信息 包括名称、类型、Tag for i := 0; i < typeS.NumField(); i++ { // 通过下标访问成员 fmt.Printf("Field(%v):%+v\n", i, typeS.Field(i)) } // 通过名称访问成员 field, ok := typeS.FieldByName("Num") fmt.Printf("FieldByName(\"Num\") ok:%v field:%+v\n", ok, field) // 获取tag值 fmt.Printf("json tag val:%+v\n", field.Tag.Get("json")) // 获取嵌套结构体的字段 fmt.Printf("Cnt field:%+v\n", typeS.FieldByIndex([]int{2, 0})) }代码输出如下,
$ go run main.go NumField:3 Field(0):{Name:Num PkgPath: Type:int Tag:json:"num_json" orm:"column:num_orm" Offset:0 Index:[0] Anonymous:false} Field(1):{Name:Desc PkgPath: Type:string Tag:json:"desc_json" orm:"column:desc_orm" Offset:8 Index:[1] Anonymous:false} Field(2):{Name:Child PkgPath: Type:main.secStruct Tag: Offset:24 Index:[2] Anonymous:false} FieldByName("Num") ok:true field:{Name:Num PkgPath: Type:int Tag:json:"num_json" orm:"column:num_orm" Offset:0 Index:[0] Anonymous:false} json tag val:num_json Cnt field:{Name:Cnt PkgPath: Type:[]int64 Tag: Offset:0 Index:[0] Anonymous:false}3. reflect.Value
func main() { b := int32(1) valueB := reflect.ValueOf(b) fmt.Printf("reflect.TypeOf(b):%v Kind:%v\n", valueB, valueB.Kind()) s := "abcdefg" valueS := reflect.ValueOf(s) fmt.Printf("reflect.TypeOf(s):%v Kind:%v Len:%v\n", valueS, valueS.Kind(), valueS.Len()) }代码输出如下,
$ go run main.go reflect.TypeOf(b):1 Kind:int32 reflect.TypeOf(s):abcdefg Kind:string Len:73.2 结构体的成员的值
func main() { type secStruct struct { Cnt []int64 } type myStruct struct { Num int `json:"num_json" orm:"column:num_orm"` Desc string `json:"desc_json" orm:"column:desc_orm"` Child secStruct } s := myStruct{ Num: 100, Desc: "desc", Child: secStruct{[]int64{1, 2, 3}}, } valueS := reflect.ValueOf(s) // 成员数量 fmt.Printf("NumField:%v \n", valueS.NumField()) // 每个成员的值 for i := 0; i < valueS.NumField(); i++ { // 通过下标访问成员 fmt.Printf("value(%v):%+v\n", i, valueS.Field(i)) } // 通过名称访问成员 value := valueS.FieldByName("Num") fmt.Printf("FieldByName(\"Num\") value:%v\n", value) // 获取嵌套结构体的字段 fmt.Printf("Cnt field:%+v\n", valueS.FieldByIndex([]int{2, 0})) }代码输出如下
$ go run main.go NumField:3 value(0):100 value(1):desc value(2):{Cnt:[1 2 3]} FieldByName("Num") value:100 Cnt field:[1 2 3]3.3 遍历array、slice
func main() { s := []int64{1, 2, 3, 4, 5, 6} valueS := reflect.ValueOf(s) fmt.Printf("ValueOf(s):%v Kind:%v Len:%v\n", valueS, valueS.Kind(), valueS.Len()) for i := 0; i < valueS.Len(); i++ { fmt.Printf("valueS.Index(%v):%v\n", i, valueS.Index(i)) } }代码输出如下
$ go run main.go ValueOf(s):[1 2 3 4 5 6] Kind:slice Len:6 valueS.Index(0):1 valueS.Index(1):2 valueS.Index(2):3 valueS.Index(3):4 valueS.Index(4):5 valueS.Index(5):63.4 遍历map
func main() { m := map[int]string{ 1: "1", 2: "2", 3: "3", } valueM := reflect.ValueOf(m) // 迭代器访问 iter := valueM.MapRange() for iter.Next() { fmt.Printf("key:%v val:%v\n", iter.Key(), iter.Value()) } fmt.Println("------") // 通过key访问 keys := valueM.MapKeys() for i := 0; i < len(keys); i++ { fmt.Printf("key:%v val:%v\n", keys[i], valueM.MapIndex(keys[i])) } }代码输出如下,
$ go run main.go key:1 val:1 key:2 val:2 key:3 val:3 ------ key:3 val:3 key:1 val:1 key:2 val:24. 反射的三大定律
func main() { a := int32(10) valueA := reflect.ValueOf(a) fmt.Printf("ValueOf(a):%v\n", valueA) fmt.Printf("Interface():%v\n", valueA.Interface()) ai, ok := valueA.Interface().(int32) fmt.Printf("ok:%v val:%v\n", ok, ai) }代码输出如下
$ go run main.go ValueOf(a):10 Interface():10 ok:true val:104.3 通过反射修改对象,该对象值必须是可修改的
func main() { a := int32(10) valueA := reflect.ValueOf(a) fmt.Printf("valueA :%v\n", valueA.CanSet()) b := int32(100) valuePtrB := reflect.ValueOf(&b) fmt.Printf("valuePtrB:%v Elem:%v\n", valuePtrB.CanSet(), valuePtrB.Elem().CanSet()) valuePtrB.Elem().Set(reflect.ValueOf(int32(200))) fmt.Printf("b:%v Elem:%v\n", b, valuePtrB.Elem()) }代码输出如下
$ go run main.go valueA :false valuePtrB:false Elem:true b:200 Elem:200后续章节再分享通过修改各种类型的值的实操