golang-reflect反射三定律

  1. 定律一:反射可以将“接口类型变量”转换为“反射类型对象”
func TypeOf(i interface{}) Type
func ValueOf(i interface{}) Value

执行函数 reflect.TypeOf ()和 reflect.ValueOf()的入参都是作为一个接口传入,返回反射类型的对象。
在这里插入图片描述

  1. 定律二:反射可以将“反射类型对象”转换为“接口类型变量”
func (v Value) Interface() (i interface{})
package main
import (
	"fmt"
	"reflect"
)
func main() {
	var a int = 30
	v := reflect.ValueOf(a) //返回Value类型对象
	fmt.Println(v)
	v1 := v.Interface() //返回空接口变量
	v2 := v1.(int)     //类型断言,断定v1中type=int
	fmt.Printf("%T %v\n", v2, v2)
	fmt.Println(v2)
}
  1. 定律三:如果要修改“反射类型对象”,其值必须是“可写的”(settable)
    案例一:
var x float64 = 3.4
v := reflect.ValueOf(x)
fmt.Println("v:", v.CanSet())//判断可写性 false
v.SetFloat(7.1) //panic.

x到v是一个值拷贝,如果v.SetFloat(7.1)这行代码能够成功执行,它不会更新 x ,虽然看起来变量 v 是根据 x 创建的。相反,它会更新 x 存在于 反射对象 v 内部的一个拷贝,而变量 x 本身完全不受影响。这会造成迷惑,并且没有任何意义,所以是不合法的。“可写性”就是为了避免这个问题而设计的。
案例二:
既然是值拷贝,那我们传递地址会怎么样?

var x float64 = 3.4
p := reflect.ValueOf(&x) // &x.
fmt.Println("type of p:", p.Type())//*float64
fmt.Println("settability of p:", p.CanSet())//false
v.SetFloat(7.1) //panic.

同样不能做修改,这是因为v当前保存的是x的地址,而不是x的原始空间。

fmt.Println(p) //0xc420014060

因此我们可以可以调用 Value 类型的 Elem 方法。Elem 方法能够对指针进行“解引用”。

package main

import (
	"fmt"
	"reflect"
)

func main(){
	var x float64 = 3.4
	p := reflect.ValueOf(&x)
	fmt.Println(p)//0xc420014060
	fmt.Println("p:", p.CanSet())//false
	v:=p.Elem()//Elem()对指针解引用
	fmt.Println("v:", v.CanSet())//true
	v.SetFloat(6.6)
	fmt.Println(v)//6.6
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值