Reflect 反射包有2个重要的类型,分别经过Typeof()
和ValueOf()
返回。 分别在源码包里的reflect
包中的type.go
和value.go
app
TypeOf() 返回一个Type
接口类型,源码中ui
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 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 }
有一个rtype
结构体 实现了Type
接口的全部方法。源码:指针
type rtype struct { size uintptr ptrdata uintptr hash uint32 tflag tflag align uint8 fieldAlign uint8 kind uint8 alg *typeAlg gcdata *byte str nameOff ptrToThis typeOff }
TypeOf会返回一个rtype。能够调用他的方法code
例如:对象
argTest := "test" v :=reflect.TypeOf(argTest) fmt.Println(v.Kind()) //string argTest1 :=&testStruct{} v1 :=reflect.TypeOf(argTest1) fmt.Println(v1.Kind()) // ptr argTest1 :=&testStruct{} v1 :=reflect.TypeOf(*argTest1) fmt.Println(v1.Kind()) //struct argTest1 :=&testStruct{} v1 :=reflect.TypeOf(argTest1).Elem() fmt.Println(v1.Kind()) // struct
能够利用Kind()
方法来获取反射对象的类型,若是是struct
类型传入的是一个地址,会获得ptr
类型,能够传入指向地址的值或者利用Elem()
方法能够获得对应的类型。全部基础类型的基本属性均可以经过rtype
来得到。基础类型能够查看type.goKind
类型中的包含。排序
获取结构体中全部元素的属性。接口
func getStructArgProperty(t interface{}){ var v reflect.Type if reflect.TypeOf(t).Kind() == reflect.Ptr { // if reflect.TypeOf(t).Elem().Kind() != reflect.Struct{ fmt.Println("不是结构体") return } v =reflect.TypeOf(t).Elem() }else{ if reflect.TypeOf(t).Kind() != reflect.Struct{ fmt.Println("不是结构体") return } v=reflect.TypeOf(t) } run(v) } func run(v reflect.Type){ for i:=0;i<v.NumField();i++{ argType:= v.Field(i) if argType.Type.Kind() ==reflect.Ptr { fmt.Println(argType.Name,argType.Type.Elem().Kind()) }else { if argType.Type.Kind() ==reflect.Struct { fmt.Println(" =====>",argType.Name) run(argType.Type) }else { fmt.Println(argType.Name, argType.Type.Kind()) } } } }
但若要取到对象的值,则须要用到ValueOf。get
ValueOf() 返回一个Value
结构体类型,源码中源码
type Value struct { typ *rtype ptr unsafe.Pointer flag }
与rtype
的Kind()
不一样的是,其中flag 是一个uintptr
类型,实现了kind()
方法。新增了类型,源码中string
const ( flagKindWidth = 5 // there are 27 kinds flagKindMask flag = 1<<flagKindWidth - 1 flagStickyRO flag = 1 << 5 flagEmbedRO flag = 1 << 6 flagIndir flag = 1 << 7 flagAddr flag = 1 << 8 flagMethod flag = 1 << 9 flagMethodShift = 10 flagRO flag = flagStickyRO | flagEmbedRO )
利用 ValueOf
取值,赋值
arr := [...]int{1,2,3,4} v := reflect.ValueOf(arr) fmt.Println(v) //[1,2,3,4] v1 := reflect.ValueOf(&arr) fmt.Println(v1) //&[1,2,3,4] fmt.Println(v.Elem().CanSet()) // panic fmt.Println(v1.Elem().CanSet()) // true v1.Elem().Index(0).SetInt(10) fmt.Println(arr) // 10,2,3,4
Elem()
方法只区分了interface{}
ptr
,再处理指针类型的时候需先调用Elem()
方法获得一个具体的基础类型。能够利用Kind()
方法来得知ValueOf
返回的是指针仍是interfaec{}
或利用Indirect()
方法来判断。,若须要赋值则须要传入对象的指针,也就是值传递或址传递的意思。 struct
的取值,赋值只是调用了不一样方法。例如:
type student struct{ numb int name string Age int class *class } type class struct{ classNumber int className string } func structValueOf(){ s := student{numb:1,name:"john",Age:18,class:&class{classNumber:1}} v := reflect.ValueOf(&s) getStructArgProperty(v) } func getStructArgProperty(v reflect.Value){ for i:=0;i<v.NumField();i++{ argType:= reflect.Indirect(v.Field(i)) if argType.Kind()==reflect.Struct { fmt.Println("================>") getStructArgProperty(argType) }else { if argType.CanSet() == true && argType.Kind() == reflect.Int { argType.SetInt(10) } fmt.Println(argType.Kind(), " : ", argType, " ", argType.CanSet()) } } }
在须要修改的字段结构体的属性应该为公开。
若要获取类型的方法,使用TypeOf()
,ValueOf()
2中类型均可以获取。
不一样的是TypeOf()
返回方法的基本属性,但并本身没有现实调用方法,而是经过调用ValueOf
的Call()
,而ValueOf
则没有返回方法的名字等基本属性
type myType int func (my *myType) Hi(){ fmt.Println("my value ",*my) } func (my *myType) Set(x int){ *my = myType(x) } func (my myType) Get() int{ fmt.Println("my value ", my) return int(my) } var s myType = 1 v := reflect.ValueOf(&s) v1 := reflect.TypeOf(s) fmt.Println(" v ",v.NumMethod()) //3 fmt.Println(" v1 ",v1.NumMethod()) //1 传入的若是是值类型,则只返回值类型方法 for i:=0;i<v1.NumMethod();i++{ fmt.Println(v1.Method(i)) //方法名等结果,根据首字母排序 } for i:=0;i<v.NumMethod();i++{ fmt.Println(v.Method(i)) //reflect方法对象。 } var para []reflect.Value para = append(para,reflect.ValueOf(11)) fmt.Println(v.Method(2).Call(para)) //调用Set方法 para = append(para,reflect.ValueOf(&s)) fmt.Println(v1.Method(0).Func.Call(para[1:])) //调用Get方法