Go语言反射规则浅析
图:反射对象关系
反射 API
反射 API 的分类总结如下。1) 从实例到 Value
通过实例获取 Value 对象,直接使用 reflect.ValueOf() 函数。例如:func ValueOf(i interface {}) Value
2) 从实例到 Type
通过实例获取反射对象的 Type,直接使用 reflect.TypeOf() 函数。例如:func TypeOf(i interface{}) Type
3) 从 Type 到 Value
Type 里面只有类型信息,所以直接从一个 Type 接口变量里面是无法获得实例的 Value 的,但可以通过该 Type 构建一个新实例的 Value。reflect 包提供了两种方法,示例如下:
//New 返回的是一个 Value,该 Value 的 type 为 PtrTo(typ),即 Value 的 Type 是指定 typ 的指针类型
func New(typ Type) Value
//Zero 返回的是一个 typ 类型的零佳,注意返回的 Value 不能寻址,位不可改变
func Zero(typ Type) Value
func NewAt(typ Type, p unsafe.Pointer) Value
4) 从 Value 到 Type
从反射对象 Value 到 Type 可以直接调用 Value 的方法,因为 Value 内部存放着到 Type 类型的指针。例如:func (v Value) Type() Type
5) 从 Value 到实例
Value 本身就包含类型和值信息,reflect 提供了丰富的方法来实现从 Value 到实例的转换。例如:
//该方法最通用,用来将 Value 转换为空接口,该空接口内部存放具体类型实例
//可以使用接口类型查询去还原为具体的类型
func (v Value) Interface() (i interface{})
//Value 自身也提供丰富的方法,直接将 Value 转换为简单类型实例,如果类型不匹配,则直接引起 panic
func (v Value) Bool () bool
func (v Value) Float() float64
func (v Value) Int() int64
func (v Value) Uint() uint64
6) 从 Value 的指针到值
从一个指针类型的 Value 获得值类型 Value 有两种方法,示例如下。
//如果 v 类型是接口,则 Elem() 返回接口绑定的实例的 Value,如采 v 类型是指针,则返回指针值的 Value,否则引起 panic
func (v Value) Elem() Value
//如果 v 是指针,则返回指针值的 Value,否则返回 v 自身,该函数不会引起 panic
func Indirect(v Value) Value
7) Type 指针和值的相互转换
指针类型 Type 到值类型 Type。例如:
//t 必须是 Array、Chan、Map、Ptr、Slice,否则会引起 panic
//Elem 返回的是其内部元素的 Type
t.Elem() Type
//PtrTo 返回的是指向 t 的指针型 Type
func PtrTo(t Type) Type
8) Value 值的可修改性
Value 值的修改涉及如下两个方法:
//通过 CanSet 判断是否能修改
func (v Value ) CanSet() bool
//通过 Set 进行修改
func (v Value ) Set(x Value)
如果传进去的是一个指针,虽然接口内部转换的也是指针的副本,但通过指针还是可以访问到最原始的对象,所以此种情况获得的 Value 是可以修改的。下面来看一个简单的示例。
package main import ( "fmt" "reflect" ) type User struct { id int Name string Age int } func main() { u := User{Id: 1, Name:"andes", Age: 20} va := reflect.ValueOf(u) vb := reflect.ValueOf(&u) //值类型是可修改的 fmt.Println(va.CanSet(), va.FieldByName("Name").CanSet()) //false false //指针类型是可修改的 fmt.Println(vb.CanSet(), vb.Elem().FieldByName("Name").CanSet()) //false false fmt.Printf("%v\n", vb) name :="shine" vc := reflect.ValueOf(name) //通过 Set 函数修改变量的值 vb.Elem().FieldByName("Name").Set(vc) fmt.Printf("%v\n", vb) }运行结果:
false false
false true
&{1 andes 20)
&{1 shine 20)
- 反射可以从接口值得到反射对象。
- 反射可以从反射对象获得接口值。
- 若要修改一个反射对象,则其值必须可以修改。
所有教程
- socket
- Python基础教程
- C#教程
- MySQL函数
- MySQL
- C语言入门
- C语言专题
- C语言编译器
- C语言编程实例
- GCC编译器
- 数据结构
- C语言项目案例
- C++教程
- OpenCV
- Qt教程
- Unity 3D教程
- UE4
- STL
- Redis
- Android教程
- JavaScript
- PHP
- Mybatis
- Spring Cloud
- Maven
- vi命令
- Spring Boot
- Spring MVC
- Hibernate
- Linux
- Linux命令
- Shell脚本
- Java教程
- 设计模式
- Spring
- Servlet
- Struts2
- Java Swing
- JSP教程
- CSS教程
- TensorFlow
- 区块链
- Go语言教程
- Docker
- 编程笔记
- 资源下载
- 关于我们
- 汇编语言
- 大数据
- 云计算
- VIP视频