Golang Go语言中 Dig101-Go 之如何在函数内修改指针
Golang Go语言中 Dig101-Go 之如何在函数内修改指针
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 系列
更多关于Golang Go语言中 Dig101-Go 之如何在函数内修改指针的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于Golang Go语言中 Dig101-Go 之如何在函数内修改指针的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Golang(Go语言)中,通过指针传递变量可以实现在函数内部修改外部变量的值。这对于需要修改大型数据结构或者希望函数有副作用(即改变输入参数)的场景非常有用。在Dig101-Go教程中,了解如何在函数内修改指针是一个重要的知识点。
首先,你需要定义一个指针类型的变量,并将某个变量的地址赋值给这个指针。然后,将这个指针作为参数传递给函数。在函数内部,通过解引用指针(使用*
操作符)来访问和修改指针指向的值。
示例代码如下:
package main
import "fmt"
func modifyValue(ptr *int) {
*ptr = 100 // 通过解引用指针修改值
}
func main() {
var x int = 10
fmt.Println("Before:", x)
ptr := &x // 获取x的地址
modifyValue(ptr) // 传递指针
fmt.Println("After:", x) // x的值已被修改
}
在这个例子中,modifyValue
函数接收一个指向int
类型的指针作为参数。通过解引用ptr
,函数内部修改了ptr
指向的值,即main
函数中的变量x
。
理解指针和如何在函数间传递指针是掌握Go语言内存管理和函数参数传递的重要一步。希望这个解释能帮助你更好地掌握Dig101-Go中关于在函数内修改指针的内容。如果有进一步的问题,欢迎继续提问!