This is a creation in Article, where the information may have evolved or changed.
Reflect Bag
The Reflect Reflex Pack has 2 important types, which are passed Typeof()
and ValueOf()
returned respectively. Separately in the package of the source code package reflect
type.go
andvalue.go
Type
TypeOf () returns an Type
interface type, in the source code
type Type interface {Align() intFieldAlign() intMethod(int) MethodMethodByName(string) (Method, bool)NumMethod() intName() stringPkgPath() stringSize() uintptrString() stringKind() KindImplements(u Type) boolConvertibleTo(u Type) boolComparable() boolBits() intChanDir() ChanDirIsVariadic() boolElem() TypeField(i int) StructFieldFieldByIndex(index []int) StructFieldFieldByName(name string) (StructField, bool)FieldByNameFunc(match func(string) bool) (StructField, bool)In(i int) TypeKey() TypeLen() intNumField() intNumIn() intNumOut() intOut(i int) Typecommon() *rtypeuncommon() *uncommonType}
There is a rtype
struct that implements Type
all the methods of the interface. Source:
type rtype struct {size uintptrptrdata uintptr hash uint32 tflag tflag align uint8 fieldAlign uint8 kind uint8 alg *typeAlg gcdata *byte str nameOff ptrToThis typeOff }
TypeOf will return a rtype. Can call his method.
For example:
argTest := "test"v :=reflect.TypeOf(argTest)fmt.Println(v.Kind()) //stringargTest1 :=&testStruct{}v1 :=reflect.TypeOf(argTest1)fmt.Println(v1.Kind()) // ptrargTest1 :=&testStruct{}v1 :=reflect.TypeOf(*argTest1)fmt.Println(v1.Kind()) //structargTest1 :=&testStruct{}v1 :=reflect.TypeOf(argTest1).Elem()fmt.Println(v1.Kind()) // struct
The method can be used Kind()
to get the type of the reflected object, if the struct
type is passed in an address, it gets the ptr
type, it can pass in the value of the address, or Elem()
the corresponding type can be obtained by using the method. The basic properties of all underlying types are available through rtype
. The underlying type can view Kind
the inclusions in the Type.go type.
Gets the properties of all the elements in the struct.
func getStructArgProperty(t interface{}){var v reflect.Typeif 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())}}}}
However, to fetch the value of an object, you need to use the valueof.
Value
ValueOf () returns a Value
struct type, in source code
type Value struct {typ *rtypeptr unsafe.Pointerflag}
The rtype
Kind()
difference is that the flag is a uintptr
type that implements the kind()
method. New type, in the source code
const (flagKindWidth = 5 // there are 27 kindsflagKindMask flag = 1<<flagKindWidth - 1flagStickyRO flag = 1 << 5flagEmbedRO flag = 1 << 6flagIndir flag = 1 << 7flagAddr flag = 1 << 8flagMethod flag = 1 << 9flagMethodShift = 10flagRO flag = flagStickyRO | flagEmbedRO)
Using ValueOf
values to assign values
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()) // panicfmt.Println(v1.Elem().CanSet()) // truev1.Elem().Index(0).SetInt(10)fmt.Println(arr) // 10,2,3,4
The
Elem ()
method only distinguishes between interface{}
ptr
, and then you need to call Elem ()
when handling pointer types method to get a concrete base type. You can use the Kind ()
method to know whether ValueOf
returns a pointer or interfaec{}
, and if you need to assign a value, you need to pass in a pointer to the object, which is the meaning of value passing or addressing. The value of the struct
, and the assignment only calls a different method. For example:
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++{ //NumField()会判断Kind()是否为struct 不是的话会panicargType:= v.Field(i)if argType.Kind() == reflect.Ptr{if argType.Elem().Kind() == reflect.Struct{fmt.Println("========>")getStructArgProperty(argType.Elem())}else {fmt.Println(argType.Elem().Kind()," : ",argType ," ",argType.Elem().CanSet())}}else {if argType.Kind()==reflect.Struct {getStructArgProperty(argType)}else {if argType.CanSet() == true && argType.Kind() == reflect.Int {argType.SetInt(10)}fmt.Println(argType.Kind(), " : ", argType, " ", argType.CanSet())}}}}
The properties of the field structure body that need to be modified should be public.
Types of methods
To get the method of a type, use TypeOf()
the ValueOf()
2 type to get it.
The difference is that the TypeOf()
basic properties of the return method, but not the actual call method, but by calling ValueOf
Call()
, and ValueOf
then not returning the name of the method and other basic properties
type myType intfunc (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 = 1v := reflect.ValueOf(&s)v1 := reflect.TypeOf(s)fmt.Println(" v ",v.NumMethod()) //3fmt.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.Valuepara = 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方法