跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • Dig101-Go 之如何在函数内修改指针
未分類
22 5 月 2020

Dig101-Go 之如何在函数内修改指针

Dig101-Go 之如何在函数内修改指针

資深大佬 : newmiao 2

Dig101: dig more, simplified more and know more

今天来看一个小问题:如何在函数内部修改一个指针(参数或接收者),使其值的改变能反映在函数外部?

直接上代码,这样可以么?

type ArgType struct {   A string   b int }  func modifyPointerArg1(arg *ArgType) {   arg = &ArgType{"arg1", 1}   fmt.Println("inside modifyPointerArg1:", arg) } 

答案是 [不可以]

等会分析,再看一个,这个呢?

func modifyPointerArg2(arg *ArgType) {   *arg = ArgType{"arg2", 2}   fmt.Println("inside modifyPointerArg2:", arg) } 

答案是 [可以]

仔细看下,你应该就明白了。

第一个替换的是指针变量本身,

也就是在函数modifyPointerArg1的作用域内,其修改是有效

函数返回后,并不影响指针arg所指向的值(别忘了,Go 参数传递是值传递嘛!)

至于modifyPointerArg2则是对指针解引用,修改了其指向的值

这样的方式其实还有很多,比如这个:

func modifyPointerArg3(arg *ArgType) {   val := reflect.ValueOf(arg)   val.Elem().FieldByName("A").SetString("arg3")   fmt.Println("inside modifyPointerArg3:", arg)   // val.Elem().FieldByName("b").SetInt(3)   // panic: reflect: reflect.flag.mustBeAssignable using value obtained using unexported field } 

实际是利用反射的Elem()获取val的值

  • 如果其为空接口(empty interface),则获取其内部值(空接口值字段的类型是指针哦)
  • 如果其为指针(pointer),则获取其指向的值

获取到的结构如下

type Value struct {     // 类型     typ *rtype     // 值指针     ptr unsafe.Pointer     // 标志位   flag } 

然后对应类型修改时, 实际就是对指针解引用修改其指向的值

func (v Value) SetString(x string) {   v.mustBeAssignable()   v.mustBe(String)   // 这里   *(*string)(v.ptr) = x } 

Tips: 这里注意一点,不导出的字段(结构体内小写的字段)不能用此类方法修改,会 panic !

再如:

func modifyPointerArg4(arg *ArgType) {   jsonStr := `{"A":"arg4","b":4}`   json.Unmarshal([]byte(jsonStr), arg) } 

内部实际也是用了反射修改指针指向的值

另外,把上边几个测试函数由指针参数换为指针接受者,也是一样的

比如:

func (arg *ArgType) modifyPointerReceiver4() {   jsonStr := `{"A":"arg4","b":4}`   json.Unmarshal([]byte(jsonStr), arg) } 

有兴趣可以去自行尝试下其他几个函数。

说了这么多,这样修改有啥用么?

常见的一个场景便是:

测试时,可以通过对接口实现对应的 mock 函数,改变参数或接收者,以达到排除依赖,进行单元测试的目的。

文章首发公众号:newbmiao

推荐阅读:Dig101-Go 系列

Dig101-Go 之如何在函数内修改指针

大佬有話說 (0)

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具