一直以为自己了解了引用传递,没想到再次打破了自己的认知,所以开一篇文章,来记录一下到目前所知(本人不敢说自己已经完全掌握了)。
从书中了解到,map,slice 都是引用传递。有以下场景需要区分。
Map
变量赋值与改变其中某个元素的值
func main() {
a := map[string]string{"a": "a"}
newA := a
for key, _ := range a {
if key == "a" {
a[key] = "A"
}
}
fmt.Println(a) // map[a:A]
fmt.Println(newA) // map[a:A]
a = map[string]string{}
fmt.Println(a) // map[]
fmt.Println(newA) // map[a:A]
}
结论:
- 变量赋值后,改变旧变量(a)的某个元素的值,新变量(newA)对应的元素也会改变。
- 变量赋值后,旧变量(a)重新赋值,新变量(newA)的值并不变。
推测:
- 变量赋值是改变了变量的地址指向,而不是将对应的值改为新值。
作为函数参数与赋值或改变一个元素的值
func main() {
a := map[string]string{"a": "a"}
b := map[string]string{"b": "b"}
passAsParams(a, b)
fmt.Println(a) // map[a:a m:m]
fmt.Println(b) // map[b:b]
}
func passAsParams(m, n map[string]string) {
m["m"] = "m"
n = map[string]string{
"n": "n",
}
}
结论:
- 作为函数参数传入时,修改其中一个元素或者直接赋一个新值,都会改变函数外的值。
推测:
- 作为函数参数传入时,传入的是个引用地址,对于在地址上的赋值,会更新函数外的值。
Slice
变量赋值与改变一个元素的值
func main() {
a := []string{"a", "b", "c", "d"}
b := a
c := a[0:3]
d := []string{"d"}
e := d
d = []string{"g", "h"}
a[1] = "f"
fmt.Println(a) // [a f c d]
fmt.Println(b) // [a f c d]
fmt.Println(c) // [a f c]
fmt.Println(d) // [g h]
fmt.Println(e) // [d]
}
结论:
- (a、b、c 比较) 对于切片旧变量(a),赋值给新变量(b)或取切片的切片给新变量(c),改变旧变量的某一个元素的值后,新变量的值都变化。
- (用两变量 d 与 e 比较)对于切片旧变量(d),赋值给新变量(e),旧变量(d)重新赋一个立即数的切片后,新变量(e)不变。
有疑问加站长微信联系(非本文作者)