反射的特点
- 反射功能具有强大的功能
- 反射是用程序检查其所拥有的结构,尤其是类型的一种能力
- 是元编程的一种形式
- 我们可以在【运行时】通过反射来分析一个结构体
- 检查其类型和变量(类型和取值)和方法
- 动态的修改变量和调用方法
- 这对于没有源代码的包尤其有用
- 这是一个强大的工具,除非真的有必要,否则应当避免使用或者小心使用
反射API
TypeOf
代码语言:javascript复制oType := reflect.TypeOf(obj)
t.Name()
kind := oType.Kind()
kind:struct 系统类型的枚举
type: 具体的类
t.NumField()
t.NumMethod()
structField := oType.Field(i)
structField.Name
structField.Type
method := oType.Method(i)
methodType := methodType
argNum := method.Type.NumIn() 参数个数
artType := method.Type.In(0) 第1个参数类型
t.FieldByIndex([]int{0, 1})
找出第0个父结构体中的第1个属性
ValueOf
oValue := reflect.ValueOf(obj) field := oValue.Field(i) -> fieldValue :=value.Field(i).Interface{}(获取第i个属性的值的“正射”形式)
代码语言:javascript复制fieldValue := value.FieldByIndex([]int{0, 0}).Interface() 找出第0个父结构体中的第0个属性值
oPtrValue.Elem() 获取地址value中的值value
oPtrValue.Elem().CanSet() 检查当前地址value内的值是否可以改变(可改变条件:可寻址 不来字非导出字段)
oPtrValue.Elem().SetInt(999)
value.SetString("jack")
nameValue := value.FieldByName("Name")
isVaild := value.IsVaild() nil(0值)非法 非常罕见
kind := value.Kind()和type.Kind()一样
mathod := oValue.Method(i) 通过方法的值可以调取方法
methodValue.Call([]reflect.Value{val1,val2})
代码实例(简单类型的反射操作)
代码语言:javascript复制package main
import (
"fmt"
"reflect"
)
//简单类型的反射
func reflectTest01(b interface{}) {
//通过反射来获取传入变量的 type,kind。值
//1.先获取到reflect.Type
rType := reflect.TypeOf(b)
fmt.Println("rType = ", rType)
//2.获取到reflect.Value
rVal := reflect.ValueOf(b)
n2 := 2 rVal.Int()
fmt.Println("n2 = ", n2)
fmt.Printf("rVal = %v, rVal type=%Tn", rVal, rVal)
//下面我们将rVal转换成interface
iv := rVal.Interface()
//将interface通过断言转换成需要的类型
num2 := iv.(int)
fmt.Println("num2 = ", num2)
}
//复杂类型的反射
func reflectTest02(b interface{}) {
//通过反射获取到传入变量的type kind值
rType := reflect.TypeOf(b)
fmt.Println("rType =", rType)
//获取到reflectValue
rVal := reflect.ValueOf(b)
//获取变量对应的kind
typeKind := rType.Kind()
valKind := rVal.Kind()
fmt.Printf("typeKind = %v, valKind = %vn", typeKind, valKind)
//将rVal转换为interface{}
iv := rVal.Interface()
fmt.Printf("iv = %v is type =%Tn", iv, iv)
//把interface{}通过断言转换成需要的类型
stu, ok := iv.(Student)
if ok {
fmt.Println("stu.Name = ", stu.Name)
}
}
func changeValue(b interface{}) {
rVal := reflect.ValueOf(b)
fmt.Printf("rVal kind =%vn", rVal.Kind())
rVal.Elem().SetInt(1)
}
type Student struct {
Name string
Age int
}
func main() {
var b int = 10
reflectTest01(b)
fmt.Println("-------------")
stu := Student{
Name: "tom",
Age: 12,
}
reflectTest02(stu)
fmt.Println("-------------")
var c int = 100
changeValue(&c)
fmt.Println(c)
}
反射操作相关代码(结构体)
代码语言:javascript复制package main
import (
"fmt"
"reflect"
)
type Monster struct {
Name string `json:"name"`
Age int `json:"age"`
Score float32
Sex string
}
func (s Monster) Print() {
fmt.Println("-----start-------")
fmt.Println(s)
fmt.Println("-----end-------")
}
func (s Monster) GetSum(n1, n2 int) int {
return n1 n2
}
func (s Monster) Set(name string, age int, score float32, sex string) {
s.Name = name
s.Age = age
s.Score = score
s.Sex = sex
}
func TestStruct(a interface{}) {
rType := reflect.TypeOf(a)
rVal := reflect.ValueOf(a)
kd := rVal.Kind()
if kd != reflect.Struct {
fmt.Println("expect struct")
return
}
num := rVal.NumField()
fmt.Println("struct fields:", num)
//变量结构体的所有字段
for i := 0; i < num; i {
fmt.Printf("field %d:值为:%vn", i, rVal.Field(i))
tagVal := rType.Field(i).Tag.Get("json")
if tagVal != "" {
fmt.Printf("field %d: tag为=%vn", i, tagVal)
}
}
//结构体的方法操作
numOfMethod := rVal.NumMethod()
fmt.Printf("struct has %d methodsn", numOfMethod)
//var params []reflect.Value
rVal.Method(1).Call(nil)
//调用结构体的第1个方法Method(0)
var params []reflect.Value
params = append(params, reflect.ValueOf(10))
params = append(params, reflect.ValueOf(40))
res := rVal.Method(0).Call(params)
fmt.Println("res = ", res[0].Int())
//反射修改字段
}
func main() {
var a Monster = Monster{
Name: "tom",
Age: 100,
Score: 30.1,
Sex: "男",
}
TestStruct(a)
}