Go_反射
反射 : 在运行时动态获取变量相关信息
reflect包
reflect.TypeOf 获取变量的类型, 返回reflect.Type类型 func TypeOf(i interface{}) Type{} reflect.ValueOf, 获取变量的值, 返回reflect.Value类型 func ValueOf(i interface{}) Value {} reflect.Value.King, 获取变量类别, 返回一个常量 func (v Value) Kind() Kind {} reflect.Value.Interface(), 转化成interface{}类型 func (v Value) Interface() (i interface{}) {}
测试
package main import ( "fmt" "reflect" ) func test(b interface{}){ t:= reflect.TypeOf(b) fmt.Println(t) // int 能得到具体的类型 v := reflect.ValueOf(b) // Value类型有许多的方法, Value.Kind() 获得类别 kd := v.Kind() if kd != reflect.Struct{ fmt.Println("这不是个结构体") // reflect.Struct是一个常量, 可以通过kd和他来判断传进来的是不是结构体, 还有其他类型 } } func main(){ var a int = 200 test(a) }
Value取值修改
func test(b interface{}){ t:= reflect.TypeOf(b) fmt.Println(t) // int 能得到具体的类型 v := reflect.ValueOf(b) // Value类型有许多的方法, Value.Kind() 获得类别 v.Int() // 取值, 对应类型 v.Elem().Int() // 指针取值, 对应类型 v.SetInt(100) // 非指针修改, 对应类型 v.Elem().SetInt(100) // 指针修改, 对应类型 }
操作字段与方法
根据名称获取
package main import ( "fmt" "reflect" ) type Student struct{ name string age int } func (stu Student) Run(){ fmt.Println("跑起来吧") } func test(b interface{}){ t:= reflect.TypeOf(b) fmt.Println(t) // int 能得到具体的类型 val := reflect.ValueOf(b) // Value类型有许多的方法, Value.Kind() 获得leibie fmt.Println(val.FieldByName("name").String()) val.MethodByName("Run").Call(nil) } func main(){ var a Student a = Student{"王二小", 18} test(a) }
循环获取
字段
package main import ( "fmt" "reflect" ) type AA struct{ name string age int } func test(b interface{}){ t:= reflect.TypeOf(b) fmt.Println(t) // int 能得到具体的类型 val := reflect.ValueOf(b) // Value类型有许多的方法, Value.Kind() 获得类别 for i:=0;i<val.NumField();i++{ // 获取类型的字段数量, if val.Field(i).Kind() == reflect.Int{ // 取到字段并且判断类别 fmt.Println(val.Field(i).Int()) } // 得到的也是Value对象 } } func main(){ var a AA a = AA{"王二小", 18} test(a) }
方法
package main import ( "fmt" "reflect" ) type Student struct{ name string age int } func (stu Student) Run(){ fmt.Println("跑起来吧") } func test(b interface{}){ t:= reflect.TypeOf(b) fmt.Println(t) // int 能得到具体的类型 val := reflect.ValueOf(b) // Value类型有许多的方法, Value.Kind() 获得leibie fmt.Println(val.NumMethod()) for i:=0;i<val.NumMethod();i++{ fmt.Println(val.Method(i).Call(nil)) // 拿到函数并调用 } } func main(){ var a Student a = Student{"王二小", 18} test(a) }
通过反射访问Tag
package main import ( "fmt" "reflect" ) type Student struct{ Name string `json:"name"` Age int `json:"age"` } func (stu Student) Run(){ fmt.Println("跑起来吧") } func test(b interface{}){ val := reflect.TypeOf(b) // val.Elem().FieldByName("Name").Tag.Get("json") fmt.Println(val.Field(1).Tag.Get("json")) // 获取字段Tag的json内容, 可以用FieldByName,不过他有俩返回值 } func main(){ var a Student a = Student{"王二小", 18} test(a) }