understand reflection by example 通过代码了解反射

guoapeng · · 676 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

通过代码学习 reflection, 直接上代码 代码如下: ```go package main import ( "fmt" "reflect" ) type Student struct { name string age int `` } func (s *Student) Study() { fmt.Print("Studying reflection...") } func (s Student) Learn() { fmt.Print("Learning reflection...") } type MyStudent Student func main() { var obj interface{} //int obj = 1 ShowObjInfo(obj) //*int value := 2 ShowObjInfo(&value) //string obj = "hello world!" ShowObjInfo(obj) //*string str := "hello world!" ShowObjInfo(&str) //map obj = map[string]string{"key1": "value1", "key2": "value2"} ShowObjInfo(obj) //slice obj = []string{"eagle", "guo"} ShowObjInfo(obj) //type alias type MyInt int obj = MyInt(1) ShowObjInfo(obj) obj = MyStudent{name: "eagle"} ShowObjInfo(obj) //chan obj = make(chan Student) ShowObjInfo(obj) //struct obj = Student{name: "eagle", age: 10} ShowObjInfo(obj) //*struct obj = &Student{name: "eagle", age: 10} ShowObjInfo(obj) // func obj = func(i Student) {} ShowObjInfo(obj) // reflect.Value and reflect.rType itself ShowObjInfo(reflect.TypeOf(obj)) ShowObjInfo(reflect.ValueOf(obj)) fmt.Println("== 通过反射修改对象=====") var num float64 = 1.2345 fmt.Println("value to modify of pointer:", num) // 通过reflect.ValueOf获取num中的reflect.Value,注意,参数必须是指针才能修改其值 //pointer := reflect.ValueOf(num) // note the difference better num and &num pointer := reflect.ValueOf(&num) newValue := pointer.Elem() fmt.Println("settability of pointer:", pointer.CanSet()) fmt.Println("settability of newValue:", newValue.CanSet()) // 重新赋值 newValue.SetFloat(77) fmt.Println("type of newValue:", newValue.Type()) //newValue.SetInt(30) //panic switch xx := newValue.Interface().(type) { default: fmt.Println("new value of pointer:", xx) fmt.Printf("new value of pointer type: %T\n", xx) } student2 := Student{name: "eagle", age: 10} switch xx := reflect.ValueOf(student2).Interface().(type) { default: fmt.Println("value of student2 is", xx) fmt.Printf("type of student2 is %T\n", xx) } fmt.Println("new value of pointer:", num) } func ShowObjInfo(obj interface{}) { t := reflect.TypeOf(obj) v := reflect.ValueOf(obj) fmt.Printf("====================%v======================\n", t) fmt.Printf("type is %v, value is %v\n", t, v) //fmt.Printf("kind is %v\n", t.Kind()) //both methods are ok to get kind fmt.Printf("kind is %v\n", v.Type().Kind()) fmt.Printf("the name of the type is %v\n", t.Name()) fmt.Printf("the full name of the type is %v\n", t.String()) fmt.Printf("the size of the type is %v\n", t.Size()) switch t.Kind() { case reflect.Ptr: p := v.Elem() typeOfT := p.Type() fmt.Printf("kind is %v, type is %v\n", p.Kind(), typeOfT) switch p.Kind() { case reflect.Struct: if p.NumField() > 0 { fmt.Println("-- fields:") } for i := 0; i < p.NumField(); i++ { fmt.Printf(" -- %v: %v %v = %v\n", i, typeOfT.Field(i).Name, typeOfT.Field(i).Type, reflect.ValueOf(p.Field(i)).Interface()) } if typeOfT.NumMethod() > 0 { fmt.Println("-- methods :") for i := 0; i < typeOfT.NumMethod(); i++ { fmt.Printf(" -- %v: name: %v, %v\n", i, typeOfT.Method(i).Name, typeOfT.Method(i).Type) } } if t.NumMethod() > 0 { fmt.Println("-- methods:") for i := 0; i < t.NumMethod(); i++ { fmt.Printf(" -- %v: name: %v, %v\n", i, t.Method(i).Name, t.Method(i).Type) } } } case reflect.Struct: fmt.Printf("the num of fields is %v and the mum of method is %v \n", t.NumField(), t.NumMethod()) if t.NumField() > 0 { fmt.Println("-- fields:") } for i := 0; i < t.NumField(); i++ { fmt.Printf(" -- %v: %v %v = %v\n", i, t.Field(i).Name, t.Field(i).Type, reflect.ValueOf(v.Field(i)).Interface()) } if t.NumMethod() > 0 { fmt.Println("-- methods:") for i := 0; i < t.NumMethod(); i++ { fmt.Printf(" -- %v: name: %v, %v\n", i, t.Method(i).Name, t.Method(i).Type) } } default: fmt.Printf("the mum of method is %v \n", t.NumMethod()) if t.NumMethod() > 0 { fmt.Println("-- methods") for i := 0; i < t.NumMethod(); i++ { fmt.Printf(" -- %v: name: %v, %v\n", i, t.Method(i).Name, t.Method(i).Type) } } } } ``` 输出如下 ```bash ====================int====================== type is int, value is 1 kind is int the name of the type is int the full name of the type is int the size of the type is 8 the mum of method is 0 ====================*int====================== type is *int, value is 0xc00000a0d8 kind is ptr the name of the type is the full name of the type is *int the size of the type is 8 kind is int, type is int ====================string====================== type is string, value is hello world! kind is string the name of the type is string the full name of the type is string the size of the type is 16 the mum of method is 0 ====================*string====================== type is *string, value is 0xc000042220 kind is ptr the name of the type is the full name of the type is *string the size of the type is 8 kind is string, type is string ====================map[string]string====================== type is map[string]string, value is map[key1:value1 key2:value2] kind is map the name of the type is the full name of the type is map[string]string the size of the type is 8 the mum of method is 0 ====================[]string====================== type is []string, value is [eagle guo] kind is slice the name of the type is the full name of the type is []string the size of the type is 24 the mum of method is 0 ====================main.MyInt====================== type is main.MyInt, value is 1 kind is int the name of the type is MyInt the full name of the type is main.MyInt the size of the type is 8 the mum of method is 0 ====================main.MyStudent====================== type is main.MyStudent, value is {eagle 0} kind is struct the name of the type is MyStudent the full name of the type is main.MyStudent the size of the type is 24 the num of fields is 2 and the mum of method is 0 -- fields: -- 0: name string = eagle -- 1: age int = 0 ====================chan main.Student====================== type is chan main.Student, value is 0xc000046060 kind is chan the name of the type is the full name of the type is chan main.Student the size of the type is 8 the mum of method is 0 ====================main.Student====================== type is main.Student, value is {eagle 10} kind is struct the name of the type is Student the full name of the type is main.Student the size of the type is 24 the num of fields is 2 and the mum of method is 1 -- fields: -- 0: name string = eagle -- 1: age int = 10 -- methods: -- 0: name: Learn, func(main.Student) ====================*main.Student====================== type is *main.Student, value is &{eagle 10} kind is ptr the name of the type is the full name of the type is *main.Student the size of the type is 8 kind is struct, type is main.Student -- fields: -- 0: name string = eagle -- 1: age int = 10 -- methods : -- 0: name: Learn, func(main.Student) -- methods: -- 0: name: Learn, func(*main.Student) -- 1: name: Study, func(*main.Student) ====================func(main.Student)====================== type is func(main.Student), value is 0x4c5730 kind is func the name of the type is the full name of the type is func(main.Student) the size of the type is 8 the mum of method is 0 ====================*reflect.rtype====================== type is *reflect.rtype, value is func(main.Student) kind is ptr the name of the type is the full name of the type is *reflect.rtype the size of the type is 8 kind is struct, type is reflect.rtype -- fields: -- 0: size uintptr = 8 -- 1: ptrdata uintptr = 8 -- 2: hash uint32 = 3604702347 -- 3: tflag reflect.tflag = 2 -- 4: align uint8 = 8 -- 5: fieldAlign uint8 = 8 -- 6: kind uint8 = 51 -- 7: alg *reflect.typeAlg = &{<nil> <nil>} -- 8: gcdata *uint8 = 0x51f99a -- 9: str reflect.nameOff = 36918 -- 10: ptrToThis reflect.typeOff = 0 -- methods: -- 0: name: Align, func(*reflect.rtype) int -- 1: name: AssignableTo, func(*reflect.rtype, reflect.Type) bool -- 2: name: Bits, func(*reflect.rtype) int -- 3: name: ChanDir, func(*reflect.rtype) reflect.ChanDir -- 4: name: Comparable, func(*reflect.rtype) bool -- 5: name: ConvertibleTo, func(*reflect.rtype, reflect.Type) bool -- 6: name: Elem, func(*reflect.rtype) reflect.Type -- 7: name: Field, func(*reflect.rtype, int) reflect.StructField -- 8: name: FieldAlign, func(*reflect.rtype) int -- 9: name: FieldByIndex, func(*reflect.rtype, []int) reflect.StructField -- 10: name: FieldByName, func(*reflect.rtype, string) (reflect.StructField, bool) -- 11: name: FieldByNameFunc, func(*reflect.rtype, func(string) bool) (reflect.StructField, bool) -- 12: name: Implements, func(*reflect.rtype, reflect.Type) bool -- 13: name: In, func(*reflect.rtype, int) reflect.Type -- 14: name: IsVariadic, func(*reflect.rtype) bool -- 15: name: Key, func(*reflect.rtype) reflect.Type -- 16: name: Kind, func(*reflect.rtype) reflect.Kind -- 17: name: Len, func(*reflect.rtype) int -- 18: name: Method, func(*reflect.rtype, int) reflect.Method -- 19: name: MethodByName, func(*reflect.rtype, string) (reflect.Method, bool) -- 20: name: Name, func(*reflect.rtype) string -- 21: name: NumField, func(*reflect.rtype) int -- 22: name: NumIn, func(*reflect.rtype) int -- 23: name: NumMethod, func(*reflect.rtype) int -- 24: name: NumOut, func(*reflect.rtype) int -- 25: name: Out, func(*reflect.rtype, int) reflect.Type -- 26: name: PkgPath, func(*reflect.rtype) string -- 27: name: Size, func(*reflect.rtype) uintptr -- 28: name: String, func(*reflect.rtype) string ====================reflect.Value====================== type is reflect.Value, value is <func(main.Student) Value> kind is struct the name of the type is Value the full name of the type is reflect.Value the size of the type is 24 the num of fields is 3 and the mum of method is 60 -- fields: -- 0: typ *reflect.rtype = &{8 8 3604702347 2 8 8 51 0x5d43c0 0x51f99a 36918 0} -- 1: ptr unsafe.Pointer = 0x50b090 -- 2: flag reflect.flag = 19 -- methods: -- 0: name: Addr, func(reflect.Value) reflect.Value -- 1: name: Bool, func(reflect.Value) bool -- 2: name: Bytes, func(reflect.Value) []uint8 -- 3: name: Call, func(reflect.Value, []reflect.Value) []reflect.Value -- 4: name: CallSlice, func(reflect.Value, []reflect.Value) []reflect.Value -- 5: name: CanAddr, func(reflect.Value) bool -- 6: name: CanInterface, func(reflect.Value) bool -- 7: name: CanSet, func(reflect.Value) bool -- 8: name: Cap, func(reflect.Value) int -- 9: name: Close, func(reflect.Value) -- 10: name: Complex, func(reflect.Value) complex128 -- 11: name: Convert, func(reflect.Value, reflect.Type) reflect.Value -- 12: name: Elem, func(reflect.Value) reflect.Value -- 13: name: Field, func(reflect.Value, int) reflect.Value -- 14: name: FieldByIndex, func(reflect.Value, []int) reflect.Value -- 15: name: FieldByName, func(reflect.Value, string) reflect.Value -- 16: name: FieldByNameFunc, func(reflect.Value, func(string) bool) reflect.Value -- 17: name: Float, func(reflect.Value) float64 -- 18: name: Index, func(reflect.Value, int) reflect.Value -- 19: name: Int, func(reflect.Value) int64 -- 20: name: Interface, func(reflect.Value) interface {} -- 21: name: InterfaceData, func(reflect.Value) [2]uintptr -- 22: name: IsNil, func(reflect.Value) bool -- 23: name: IsValid, func(reflect.Value) bool -- 24: name: Kind, func(reflect.Value) reflect.Kind -- 25: name: Len, func(reflect.Value) int -- 26: name: MapIndex, func(reflect.Value, reflect.Value) reflect.Value -- 27: name: MapKeys, func(reflect.Value) []reflect.Value -- 28: name: MapRange, func(reflect.Value) *reflect.MapIter -- 29: name: Method, func(reflect.Value, int) reflect.Value -- 30: name: MethodByName, func(reflect.Value, string) reflect.Value -- 31: name: NumField, func(reflect.Value) int -- 32: name: NumMethod, func(reflect.Value) int -- 33: name: OverflowComplex, func(reflect.Value, complex128) bool -- 34: name: OverflowFloat, func(reflect.Value, float64) bool -- 35: name: OverflowInt, func(reflect.Value, int64) bool -- 36: name: OverflowUint, func(reflect.Value, uint64) bool -- 37: name: Pointer, func(reflect.Value) uintptr -- 38: name: Recv, func(reflect.Value) (reflect.Value, bool) -- 39: name: Send, func(reflect.Value, reflect.Value) -- 40: name: Set, func(reflect.Value, reflect.Value) -- 41: name: SetBool, func(reflect.Value, bool) -- 42: name: SetBytes, func(reflect.Value, []uint8) -- 43: name: SetCap, func(reflect.Value, int) -- 44: name: SetComplex, func(reflect.Value, complex128) -- 45: name: SetFloat, func(reflect.Value, float64) -- 46: name: SetInt, func(reflect.Value, int64) -- 47: name: SetLen, func(reflect.Value, int) -- 48: name: SetMapIndex, func(reflect.Value, reflect.Value, reflect.Value) -- 49: name: SetPointer, func(reflect.Value, unsafe.Pointer) -- 50: name: SetString, func(reflect.Value, string) -- 51: name: SetUint, func(reflect.Value, uint64) -- 52: name: Slice, func(reflect.Value, int, int) reflect.Value -- 53: name: Slice3, func(reflect.Value, int, int, int) reflect.Value -- 54: name: String, func(reflect.Value) string -- 55: name: TryRecv, func(reflect.Value) (reflect.Value, bool) -- 56: name: TrySend, func(reflect.Value, reflect.Value) bool -- 57: name: Type, func(reflect.Value) reflect.Type -- 58: name: Uint, func(reflect.Value) uint64 -- 59: name: UnsafeAddr, func(reflect.Value) uintptr == 通过反射修改对象===== value to modify of pointer: 1.2345 settability of pointer: false settability of newValue: true type of newValue: float64 new value of pointer: 77 new value of pointer type: float64 value of student2 is {eagle 10} type of student2 is main.Student new value of pointer: 77 ``` **参考文章:** [谈谈Go语言的反射三定律](https://www.jb51.net/article/90021.htm) [一看就懂系列之Golang的反射](https://blog.csdn.net/u011957758/article/details/81193806) [Golang的反射reflect深入理解和示例](https://studygolang.com/articles/12348?fr=sidebar)

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

676 次点击  ∙  1 赞  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传