反射reflection
反射可大大提高程序的灵活性,使得interface{}有更大的发挥余地
反射使用TypeOf和ValueOf函数从接口中获取目标对象信息
反射会将匿名字段作为独立字段(匿名字段本质)
想要利用反射修改对象状态,前提是interface.data 是settable,即pointer-interface
通过反射可以动态调用方法
结构体反射
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| type User struct { Id int Name string Age int } func (u User) Hello() { fmt.Println("hello world") } func Info(o interface{}) { t := reflect.TypeOf(o) if k := t.Kind(); k != reflect.Struct { fmt.Println("xxx") return } fmt.Println("Type:", t.Name()) v := reflect.ValueOf(o) fmt.Println("Fields:") for i := 0; i < t.NumField(); i++ { f := t.Field(i) val := v.Field(i).Interface() fmt.Printf("%6s: %v = %v \n", f.Name, f.Type, val) } for i := 0; i < t.NumMethod(); i++ { m := t.Method(i) fmt.Printf("%6s: %v\n", m.Name, m.Type) } } func main() { u := User{1, "ok", 12} Info(u) }
|
通过反射调用匿名字段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| type User struct { Id int Name string Age int } type Manager struct { User title string } func main() { m := Manager{User: User{1, "ok", 19}, title: "111"} t := reflect.TypeOf(m) fmt.Printf("%#v\n", t.FieldByIndex([]int{0, 0})) }
|
通过反射修改对象状态
基本类型
1 2 3 4 5 6
| func main() { x := 12 t := reflect.ValueOf(&x) t.Elem().SetInt(111) fmt.Println(x) }
|
结构体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| func main() { u := User{1,"ok",19} Set(&u) fmt.Println(u) } type User struct { Id int Name string Age int } func Set(o interface{}) { v := reflect.ValueOf(o) if v.Kind() == reflect.Ptr && !v.Elem().CanSet() { fmt.Println("xxxx") return }else{ v = v.Elem() } f := v.FieldByName("Name") if !f.IsValid() { fmt.Println("BAD") return } if f.Kind() == reflect.String { f.SetString("success") } }
|
通过反射动态调用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| type User struct { Id int Name string Age int } func (u User) Hello(name string) { fmt.Println("hello", name, ",my name is ", u.Name) } func main() { u := User{1, "ok", 19} v := reflect.ValueOf(u) mv := v.MethodByName("Hello") args := []reflect.Value{reflect.ValueOf("hundred")} mv.Call(args) }
|
有疑问加站长微信联系(非本文作者)