go 反射
Name and Kind
可调用函数和含义,以及结果一览
1 | typeOfCat := reflect.TypeOf(cat{}) |
reflect.ValueOf()和reflect.Value
1 | valueOfA := reflect.ValueOf(a) |
通过反射获取值信息
使用反射值对象包装任意值
Go语言中,使用 reflect.ValueOf() 函数获得值的反射值对象(reflect.Value)。书写格式如下:
1 | value := reflect.ValueOf(rawValue) |
reflect.ValueOf 返回 reflect.Value 类型,包含有 rawValue 的值信息。reflect.Value 与原值间可以通过值包装和值获取互相转化。reflect.Value 是一些反射操作的重要类型,如反射调用函数。
从反射值对象获取被包装的值
Go语言中可以通过 reflect.Value 重新获得原始值。
1) 从反射值对象(reflect.Value)中获取值的方法
可以通过下面几种方法从反射值对象 reflect.Value 中获取原值,如下表所示。
方法名 | 说 明 |
---|---|
Interface() interface {} | 将值以 interface{} 类型返回,可以通过类型断言转换为指定类型 |
Int() int64 | 将值以 int 类型返回,所有有符号整型均可以此方式返回 |
Uint() uint64 | 将值以 uint 类型返回,所有无符号整型均可以此方式返回 |
Float() float64 | 将值以双精度(float64)类型返回,所有浮点数(float32、float64)均可以此方式返回 |
Bool() bool | 将值以 bool 类型返回 |
Bytes() []bytes | 将值以字节数组 []bytes 类型返回 |
String() string | 将值以字符串类型返回 |
2) 从反射值对象(reflect.Value)中获取值的例子
下面代码中,将整型变量中的值使用 reflect.Value 获取反射值对象(reflect.Value)。再通过 reflect.Value 的 Interface() 方法获得 interface{} 类型的原值,通过 int 类型对应的 reflect.Value 的 Int() 方法获得整型值。
1 | package main |
通过reflect反射修改值
判断反射值是否可以修改?CanSet(),是否能被取址CanAddr()
结构体成员中,如果字段没有被导出,即便不使用反射也可以被访问,但不能通过反射修改
指针指向的具体元素
1
2
3x := 1
v := reflect.ValueOf(&x)
v = v.Elem()slice的元素
1
2
3s := []int{1,1}
v := reflect.ValueOf(s)
e := v.Index(0)可寻址的结构体的字段(指向结构体的指针)
1
2
3
4
5
6
7type Orange struct{
Size int
}
a := Orange{99}
v := reflect.ValueOf(&a)
v = v.Elem()
field = v.FieldByName("field")可寻址的数组的元素(指向数组的指针)
1
2
3
4
5
6a := [2]int{1,1}
v := reflect.ValueOf(&a)
v = v.Elem()
vIndex = v.Index(0)
vIndex.SetInt(1)
vIndex.SetInt(1)
- | - |
---|---|
Set(x Value) | 将值设置为传入的反射值对象的值 |
Setlnt(x int64) | 使用 int64 设置值。当值的类型不是 int、int8、int16、 int32、int64 时会发生宕机 |
SetUint(x uint64) | 使用 uint64 设置值。当值的类型不是 uint、uint8、uint16、uint32、uint64 时会发生宕机 |
SetFloat(x float64) | 使用 float64 设置值。当值的类型不是 float32、float64 时会发生宕机 |
SetBool(x bool) | 使用 bool 设置值。当值的类型不是 bod 时会发生宕机 |
SetBytes(x []byte) | 设置字节数组 []bytes值。当值的类型不是 []byte 时会发生宕机 |
SetString(x string) | 设置字符串值。当值的类型不是 string 时会发生宕机 |
通过类型信息创建实例
1 | var a int |
Go语言结构体标签(Struct Tag)
结构体标签的格式
tag 格式:json:"type" id:"100"
注意:
- key:“value” 冒号后没有空格
- 两个key之间,一个空格,多一个都不行
1 | type cat struct{ |
从结构体标签中获取值
1 | typeOfCat := reflect.TypeOf(cat{}) |
常见用法
动态调用函数(无参数)
- 直接
reflect.Valueof
MethodByName
- 调用
Call
方法
1 | type T struct {} |
动态调用函数(有参数)
- 创建
reflect.Value
切片 reflect.Valueof(t).MethodByName(string)
调用Call方法传入参数
1 | type T struct{} |
接收返回值
- 返回
[]reflect.Value
- 调用
Interface()
方法,转为interface{}
类型 - 断言类型
1 | type T struct{} |
Tag解析
reflect.Typeof
有NumField
,Field根据序号索取,取其中的tag
1 | type T struct{ |
通过kind()处理不同分支
reflect.Typeof().Kind()
1 | func main() { |
判断结构体是否实现接口
- 将
nil
强转为接口指针类型,通过reflect.Typeof().Elem
获取其接口类型 reflect.Typeof
调用方法Implements
来判断
1 | type IT interface { |
直接通过接口强转判断
- 将类型转换为
reflect.Value
- 将
reflect.Value
调用Interface()方法转为接口类型 - 类型断言
1 | type ITester interface { |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Bishop!
评论
GitalkValine