概要
今天改了一段代码,调用函数时把一个 sync.Map 类型的变量作为传参,在函数内部修改 sync.Map 变量的值,发现函数处理完成后,外部的变量没有修改,后来发现 sync.Map 是一个普通的结构体,跟所有的结构体一样,golang 在把结构体类型作为函数传参时,都是值传递,即创建参数的一个副本,然后传递给函数。这也就意味着,如果你在函数内部修改了这个副本的值,那么原始的值是不会被影响的。
验证过程
函数参数类型为 *sync.Map
从运行结果来看,函数内部的修改影响了原始变量。
func main() {
var result sync.Map
result.Store(10, 11)
result.Range(func(key, value any) bool {
fmt.Printf("key=%v val=%v\n", key, value)
return true // 返回 false 则表示停止迭代
})
fmt.Println("---------------------------")
GetTaskCountValueMap(&result) // 传的是指针类型
fmt.Println("---------------------------")
result.Range(func(key, value any) bool {
fmt.Printf("key=%v val=%v\n", key, value)
return true
})
}
func GetTaskCountValueMap(result *sync.Map) {
for i := 0; i < 3; i++ {
result.Store(i, i+1)
}
result.Range(func(key, value any) bool {
fmt.Printf("key=%v val=%v\n", key, value)
return true
})
}
输出结果
key=10 val=11
---------------------------
key=0 val=1
key=1 val=2
key=2 val=3
key=10 val=11
---------------------------
key=10 val=11
key=0 val=1
key=1 val=2
key=2 val=3
函数传参类型为 sync.Map
从运行结果来看,函数内部的修改不会影响原始变量。
func main() {
var result sync.Map
result.Store(10, 11)
result.Range(func(key, value any) bool {
fmt.Printf("key=%v val=%v\n", key, value)
return true // 返回 false 则表示停止迭代
})
fmt.Println("---------------------------")
GetTaskCountValueMap(result) // 传的是普通结构体类型
fmt.Println("---------------------------")
result.Range(func(key, value any) bool {
fmt.Printf("key=%v val=%v\n", key, value)
return true
})
}
func GetTaskCountValueMap(result sync.Map) {
for i := 0; i < 3; i++ {
result.Store(i, i+1)
}
result.Range(func(key, value any) bool {
fmt.Printf("key=%v val=%v\n", key, value)
return true
})
}
输出结果
key=10 val=11
---------------------------
key=10 val=11
key=0 val=1
key=1 val=2
key=2 val=3
---------------------------
key=10 val=11
golang 函数传参提醒
结构体、数组和基本数据类型都是值传递
在Go语言中,无论是结构体还是基本数据类型,当他们作为函数参数传递时,都是值传递。如果在函数内部修改了副本的值,原始的值是不会被影响。
切片、map 是引用传递
切片看起来是被作为值传递,但实际上切片(slice)的数据结构包含了指向底层数组的指针。这就意味着,当你将切片传递给函数时,虽然它是传的值(也就是切片自身的数据结构被复制),但是复制的切片和原始的切片依然共享同一个底层数组。因此,如果你在函数中修改了复制的切片中的元素,原始切片相对应的元素也会被修改。
跟切片类似,map 传递的也是对底层数据结构的引用