大家好呀!今天咱们来聊聊Go语言反射里那个最让人又爱又恨的部分——修改反射对象的值。是不是经常遇到这种情况:你满怀信心地通过反射拿到一个变量,准备给它改头换面,结果运行时“啪叽”给你来个panic?
别问我怎么知道的,说多了都是泪啊!
其实啊,Go反射的修改操作就像是在驯服一匹倔强的野马,你得懂得它的脾气,用对方法,才能让它乖乖听话。废话不多说,今天就带你用三招彻底征服这匹“野马”!
先来个灵魂拷问:为什么不能直接改?
在开始之前,咱们得先搞清楚一个根本问题:为什么有些反射对象能改,有些就不能改?
来,看这个简单的例子:
import "reflect"
func main() {
var x float64 = 3.4
v := reflect.ValueOf(x)
v.SetFloat(7.1) // 啪!panic了!
}
运行这个代码,你会看到这样的错误:
panic: reflect: reflect.Value.SetFloat using unaddressable value
这个“unaddressable value”(不可寻址的值)就是问题的关键!
当你用reflect.ValueOf(x)时,Go创建了一个x的副本的反射对象。你想想,修改一个副本有什么意义呢?就算你改了,原来的x还是纹丝不动啊!
这就好比你想给朋友换个新手机,结果你拿着他手机的照片在那里折腾,照片上的手机再怎么变,他手里的真实手机还是老样子嘛!
第一定律:要想修改,先拿到地址
Go反射的第一条修改原则:只有可寻址的反射对象才能被修改。
那什么叫做“可寻址”呢?简单说就是这个值在内存中有个明确的地址,你知道去哪儿找它。
怎么让反射对象可寻址?用指针!
func main() {
var x float64 = 3.4
p := reflect.ValueOf(&x) // 注意这里取了地址
fmt.Println("p是可设置的吗?", p.CanSet()) // false
}
咦?还是false?别急,这里有个常见的坑:虽然p现在是指针了,但p本身指向的是指针,而不是指针指向的值。
第二定律:指针要解引用才能改值
这就要用到反射里超级重要的Elem()方法了:
func main() {
var x float64 = 3.4
p := reflect.ValueOf(&x)
v := p.

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



