反射规则
Value、Type和类型实例之间的相互转化如下图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/5d9d41d60b7c4cff8ab280d99e1ecc82.png)
1、反射API
- 从实例到Value
通过实例获取Value对象,直接使用reflect.ValueOf()函数。例如:
func ValueOf(i interface{}) Value
- 从实例到Type
通过实例获取反射对象的Type,直接使用reflect.TypeOf()函数。例如:
func TypeOf(i interface{}) Type
- 从Type到Value
Type里面只有类型信息,所以直接从一个Type接口变量里面是无法获得实例的。但可以通过该Type构建一个新实例的Value,reflect包提供了两种方法,示例如下:
func New(type Type) Value
func Zero(type Type) Value
func NewAt(type Type, p unsafe.Pointer) Value
- 从Value到Type
从反射对象Value到Type可以直接调用Value的方法,因为Value内部存放着到Type类型的指针。例如:
func (v Value)Type()Type
- 从Value到实例
Value本身就包含类型和值信息,reflect提供了丰富的方法来实现从Value到实例的转换。
例如:
func (v Value)Interface()(i interface())
func (v Value)Bool()bool
func (v Value)Float()float64
func (v Value)Int()int64
func (v Value)Uint()uint64
- 从Value的指针到值
从一个指针类型的Value获得值类型Value有两种方法,示例如下。
func (v Value)Elem()Value
func Indirect(v Value)Value
- Type指针和值的相互转换
指针类型Type到值类型Type。例如:
t.Elem()Type
值类型Type到指针类型Type。例如:
func PtrTo(t Type)Type
- Value值的可修改性
Value值的修改涉及如下两个方法
func (v Value)CanSet()bool
func (v Value)Set(x Value)
Vlue值在什么情况下可以修改?我们知道实例对象传递给接口的是一个完全的值拷贝,如果调用反射的方法reflect.ValueOf()传进去的是一个值类型变量,则获得的Value实际上是原对象的一个副本,这个Vlue是无论如何也不能被修改的。如果传进去的是一个指针,虽然接口
内部转换的也是指针的副本,但通过指针还是可以访问到最原始的对象,所以此种情况获得的Value是可以修改的。下面来看一个简单的示例。
package main
import (
"fmt"
"reflect"
)
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())
fmt.Println(vb.CanSet(), vb.Elem().FieldByName("Name").CanSet())
fmt.Printf("%v\n", vb)
name := "shine"
vc := reflect.ValueOf(name)
vb.Elem().FieldByName("Name").Set(vc)
fmt.Printf("%v\n", vb)
}
type User struct {
Id int
Name string
Age int
}
2、反射三定律
- 反射可以从接口值得到反射对象。
- 反射可以从反射对象获得接口值。
- 若要修改一个反射对象,则其值必须可以修改。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)