reflect 反射
反射:可以在运行时动态获取变量的相关信息
导入 reflect 包
reflect 包下主要是Type和Value 两个struct,
- Type封装了“类型”的属性,定义相关的东西找他;
- Value主要封装了“值”的属性,与值相关的东西找他没错。此外,他是线程安全的(或者叫goroutine安全)
reflect包下主要有两个函数:
-
func TypeOf(i interface{}) Type获取变量的类型,返回reflect.Type类型 -
func ValueOf(i interface{}) Value获取变量的值,返回reflect.Value类型
1. reflect.Value.Kind,获取变量的类别,返回⼀个常量
const (
Invalid Kind = iota
Bool
Int
Int8
Int16
Int32
Int64
Uint
Uint8
Uint16
Uint32
Uint64
Uintptr
Float32
Float64
Complex64
Complex128
Array
Chan
Func
Interface
Map
Ptr
Slice
String
Struct
UnsafePointer
)
3.reflect.TypeOf
package main
import (
"fmt"
"reflect"
)
func GetType(){
var i int
typeInfo := reflect.TypeOf(i)
fmt.Printf("%#v",typeInfo)
/*输出内容是:
&reflect.rtype{size:0x8, ptrdata:0x0, hash:0xf75371fa, tflag:0x7,
align:0x8, fieldAlign:0x8, kind:0x82,
alg:(*reflect.typeAlg)(0x53ca50), gcdata:(*uint8)(0x4d8d90),
str:1019, ptrToThis:44736}}
rtype结构体
type rtype struct {
size uintptr
ptrdata uintptr // number of bytes in the type that can contain pointers
hash uint32 // hash of type; avoids computation in hash tables
tflag tflag // extra type information flags
align uint8 // alignment of variable with this type
fieldAlign uint8 // alignment of struct field with this type
kind uint8 // enumeration for C
alg *typeAlg // algorithm table
gcdata *byte // garbage collection data
str nameOff // string form
ptrToThis typeOff // type for pointer to this type, may be zero
}
*/
}
func main(){
GetType()
}
4.获取变量的类型
package main
import (
"fmt"
"reflect"
)
func GetType(a interface{}){ //获取变量类型
typeInfo := reflect.TypeOf(a)
kindof := typeInfo.Kind()
fmt.Printf("%v\n",kindof)
}
type Student struct{
Name string
Age int
}
func main(){
var i int
var s Student
var c []string
var a [10]int
var p *int
GetType(i) //int
GetType(s) //struct
GetType(c) //slice
GetType(a) //array
GetType(p) //ptr
}
5.Type 类型的方法
package main
import (
"fmt"
"reflect"
)
func GetType(a interface{}){ //获取变量类型
typeInfo := reflect.TypeOf(a)
kindof := typeInfo.Kind()
fmt.Printf("%v\n",kindof)
}
func GetNmuberMethod(a interface{}){
typeInfo := reflect.TypeOf(a)
num_of_method := typeInfo.NumMethod()
fmt.Println(num_of_method)
}
type Student struct{
Name string
Age int
}
func(s *Student) SetName(name string){ //方法一
s.Name = name
}
func(s *Student) SetAge(age int){ //方法二
s.Age = age
}
func GetMethod(a interface{}){
typeInfo := reflect.TypeOf(a)
methodname,ok:= typeInfo.MethodByName("SetName")
if !ok {
fmt.Println("have no method name")
}else{
fmt.Println(methodname)
}
}
func main(){
var s Student
GetNmuberMethod(&s) //2 ,获取s的方法
GetMethod(&s) //typeInfo := reflect.TypeOf(a)
}
6.reflect.Value.Interface(),转换成interface{}类型
变量 <------------>interface{}<------------------------->reflect.Value
func GetValue(){
var i int =100
valueinfo := reflect.ValueOf(i) //变量i 转成Value类开
tmp := valueinfo.Interface() //value类型转成接口
val := tmp.(int) //接口转成int
fmt.Println(val)
fmt.Println(valueinfo.Int()) //获取value类型的值。
}
func main(){
GetValue() //100
}
valueinfo.Type() 类型比如 Student
valueinfo.Kind() 静态类型,struct
7.利用反射来获取变量的值
reflect.ValueOf(x).Float()
reflect.ValueOf(x).Int()
reflect.ValueOf(x).String()
reflect.ValueOf(x).Bool()
8.通过反射来改变变量的值
reflect.Value.SetXX相关⽅法,⽐如:
reflect.Value.SetFloat(),设置浮点数
reflect.Value.SetInt(),设置整数
reflect.Value.SetString(),设置字符串
func main(){
var a float64
// v :=reflect.ValueOf(a) //这是一个值类型拷贝,修改不生效 panic: reflect: reflect.Value.SetFloat using unaddressable value
v :=reflect.ValueOf(&a) //传入a的地址
// v.SetFloat(3.3)//引用类型赋值不能直接这样赋值 指针 赋值 :*地址=value panic: reflect: reflect.Value.SetFloat using unaddressable value
v.Elem().SetFloat(3.3) //反射中指针赋值
fmt.Printf("%v\n",a)//3.3
其中v.Elem()⽤来获取指针指向的变量,相当于:
var a *int;
*a = 100
9.⽤反射操作结构体
a. reflect.Value.NumField()获取结构体中字段的个数
b. reflect.Value.Method(n).Call来调⽤结构体中的⽅法
获取个数:
package main
import (
"fmt"
"reflect"
)
type Student struct{
Name string
Age int
Sex int
}
func(s *Student) Set(name string,age,sex int){
s.Name = name
s.Age = age
s.Sex = sex
}
func(s *Student) Getname(name string){
s.Name = name
}
func TestStruct(){
var s *Student = &Student{}
s.Set("www",18,1)
v := reflect.ValueOf(s)
num := v.Elem().NumField() //指针变量的字段数量
fmt.Println(num) //3
sexinfo := v.Elem().FieldByName("Sex") //获取字段信息
fmt.Println(sexinfo) //1
sexinfo.SetInt(100)
fmt.Println(s) //&{www 18 100}
}
func main(){
TestStruct() //3
}
调用结构体方法:
type Student struct{
Name string
Age int
Sex int
}
func(s *Student) Set(name string,age,sex int){
s.Name = name
s.Age = age
s.Sex = sex
}
func(s *Student) Getname(name string){
s.Name = name
}
func TestStruct_value(){
var s *Student = &Student{}
v := reflect.ValueOf(s)
setinfo := v.MethodByName("Set")
var par []reflect.Value
name := "wanghj"
age := 18
sex := 1
par = append(par,reflect.ValueOf(name))
par = append(par,reflect.ValueOf(age))
par = append(par,reflect.ValueOf(sex))
setinfo.Call(par)
fmt.Printf("%v\n",s)
}

浙公网安备 33010602011771号