Reflection (example), I hope it will be helpful to friends in need!
PrefaceReflection has its wonderful uses in many languages. In computer science, reflection refers to a class of applications that enable self-describing attacks and self-controlling attacks. This article will record the author’s notes on Golang’s reflection.
After 10 seconds, the following knowledge points will be close to you: 1. Introduction to reflection2. Why use reflection?
Text1. Introduction to reflection
Golang provides a mechanism thatupdate variablesat runtime,,
view values
call methods
, and directly operate on their2. Why use reflection? | For example, sometimes we need a function that can handle various types of values. Without knowing the type, you might write: |
---|---|
When you cannot see through an unknown type, the above code is actually not very reasonable. At this time, you need | Reflection to help you deal with it. Reflection uses the TypeOf and ValueOf functions from the interface Obtain the information of the target object and easily complete the purpose | .
1. Obtain internal information of variables | reflect provides two types to access the contents of interface variables:
TypeFunction
reflect.ValueOf()Get the value of the data in the input parameter interface, If it is empty, return
0reflect.TypeOf()<- Note that it is 0
<- Note that it is nildynamically obtains the value in the input parameter interface Type, if it is empty, return
nil
Output:##The above code
package main import ( "fmt" "reflect" ) func main() { var name string = "咖啡色的羊驼" // TypeOf会返回目标数据的类型,比如int/float/struct/指针等 reflectType := reflect.TypeOf(name) // valueOf返回目标数据的的值,比如上文的"咖啡色的羊驼" reflectValue := reflect.ValueOf(name) fmt.Println("type: ", reflectType) fmt.Println("value: ", reflectValue) }Copy after login
type: string value: 咖啡色的羊驼
2.Reflection of struct
package main import ( "fmt" "reflect" ) type Student struct { Id int Name string } func (s Student) Hello(){ fmt.Println("我是一个学生") } func main() { s := Student{Id: 1, Name: "咖啡色的羊驼"} // 获取目标对象 t := reflect.TypeOf(s) // .Name()可以获取去这个类型的名称 fmt.Println("这个类型的名称是:", t.Name()) // 获取目标对象的值类型 v := reflect.ValueOf(s) // .NumField()来获取其包含的字段的总数 for i := 0; i < t.NumField(); i++ { // 从0开始获取Student所包含的key key := t.Field(i) // 通过interface方法来获取key所对应的值 value := v.Field(i).Interface() fmt.Printf("第%d个字段是:%s:%v = %v \n", i+1, key.Name, key.Type, value) } // 通过.NumMethod()来获取Student里头的方法 for i:=0;i<t.NumMethod(); i++ { m := t.Method(i) fmt.Printf("第%d个方法是:%s:%v\n", i+1, m.Name, m.Type) } }
这个类型的名称是: Student 第1个字段是:Id:int = 1 第2个字段是:Name:string = 咖啡色的羊驼 第1个方法是:Hello:func(main.Student)
3 .Reflection of anonymous or embedded fields
package main import ( "reflect" "fmt" ) type Student struct { Id int Name string } type People struct { Student // 匿名字段 } func main() { p := People{Student{Id: 1, Name: "咖啡色的羊驼"}} t := reflect.TypeOf(p) // 这里需要加一个#号,可以把struct的详情都给打印出来 // 会发现有Anonymous:true,说明是匿名字段 fmt.Printf("%#v\n", t.Field(0)) // 取出这个学生的名字的详情打印出来 fmt.Printf("%#v\n", t.FieldByIndex([]int{0, 1})) // 获取匿名字段的值的详情 v := reflect.ValueOf(p) fmt.Printf("%#v\n", v.Field(0)) }
4. Determine whether the incoming type is the type we want######reflect.StructField{Name:"Student", PkgPath:"", Type:(*reflect.rtype)(0x10aade0), Tag:"", Offset:0x0, Index:[]int{0}, Anonymous:true} reflect.StructField{Name:"Name", PkgPath:"", Type:(*reflect.rtype)(0x109f4e0), Tag:"", Offset:0x8, Index:[]int{1}, Anonymous:false} main.Student{Id:1, Name:"咖啡色的羊驼"}Copy after login
package main import ( "reflect" "fmt" ) type Student struct { Id int Name string } func main() { s := Student{Id: 1, Name: "咖啡色的羊驼"} t := reflect.TypeOf(s) // 通过.Kind()来判断对比的值是否是struct类型 if k := t.Kind(); k == reflect.Struct { fmt.Println("bingo") } num := 1; numType := reflect.TypeOf(num) if k := numType.Kind(); k == reflect.Int { fmt.Println("bingo") } }
bingo bingo
package main import ( "reflect" "fmt" ) type Student struct { Id int Name string } func main() { s := &Student{Id: 1, Name: "咖啡色的羊驼"} v := reflect.ValueOf(s) // 修改值必须是指针类型否则不可行 if v.Kind() != reflect.Ptr { fmt.Println("不是指针类型,没法进行修改操作") return } // 获取指针所指向的元素 v = v.Elem() // 获取目标key的Value的封装 name := v.FieldByName("Name") if name.Kind() == reflect.String { name.SetString("小学生") } fmt.Printf("%#v \n", *s) // 如果是整型的话 test := 888 testV := reflect.ValueOf(&test) testV.Elem().SetInt(666) fmt.Println(test) }
main.Student{Id:1, Name:"小学生"} 666
package main import ( "fmt" "reflect" ) type Student struct { Id int Name string } func (s Student) EchoName(name string){ fmt.Println("我的名字是:", name) } func main() { s := Student{Id: 1, Name: "咖啡色的羊驼"} v := reflect.ValueOf(s) // 获取方法控制权 // 官方解释:返回v的名为name的方法的已绑定(到v的持有值的)状态的函数形式的Value封装 mv := v.MethodByName("EchoName") // 拼凑参数 args := []reflect.Value{reflect.ValueOf("咖啡色的羊驼")} // 调用函数 mv.Call(args) }
我的名字是: 咖啡色的羊驼
// 以下为截取的源代码 func TypeOf(i interface{}) Type { eface := *(*emptyInterface)(unsafe.Pointer(&i)) return toType(eface.typ) } func ValueOf(i interface{}) Value { if i == nil { return Value{} } escapes(i) return unpackEface(i) }
The above is the detailed content of Detailed explanation of Golang's reflection (example). For more information, please follow other related articles on the PHP Chinese website!