Dig101: dig more, simplified more and know more
今天来看一个小问题:如何在函数内部修改一个指针(参数或接收者)指向,使其值的改变能反映在函数外部?
直接上代码,这样可以么?
1 | type ArgType struct { |
答案是【不可以】
等会分析,再看一个,这个呢?
1 | func modifyPointerArg2(arg *ArgType) { |
答案是【可以】
仔细看下,你应该就明白了。
第一个替换的是指针变量本身,
也就是在函数modifyPointerArg1
的作用域内,其修改是有效
函数返回后,并不影响指针arg
所指向的值(别忘了,Go参数传递是值传递嘛!)
至于modifyPointerArg2
则是对指针解引用,修改了其指向的值
这样的方式其实还有很多,比如这个:
1 | func modifyPointerArg3(arg *ArgType) { |
实际是利用反射的Elem()
获取val
的值
- 如果其为空接口(
empty interface
),则获取其内部值(空接口值字段的类型是指针哦) - 如果其为指针(
pointer
),则获取其指向的值
获取到的结构如下
1 | type Value struct { |
然后对应类型修改时, 实际就是对指针解引用修改其指向的值
1 | func (v Value) SetString(x string) { |
Tips: 这里注意一点,不导出的字段(结构体内小写的字段)不能用此类方法修改,会panic!
再如:
1 | func modifyPointerArg4(arg *ArgType) { |
内部实际也是用了反射修改指针指向的值
另外,把上边几个测试函数由指针参数换为指针接受者,也是一样的
比如:
1 | func (arg *ArgType) modifyPointerReceiver4() { |
有兴趣可以去自行尝试下其他几个函数。
说了这么多,这样修改有啥用么?
常见的一个场景便是:
测试时,可以通过对接口实现对应的mock函数,改变参数或接收者,以达到排除依赖,进行单元测试的目的。
如有疑问,请文末留言交流或邮件:newbvirgil@gmail.com 本文链接 : https://newbmiao.github.io/2020/05/22/how-to-modify-a-pointer-of-go-inside.html