分享
Golang 中的引用传递与值传递
aside section ._1OhGeD · · 4413 次点击 · · 开始浏览这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。
一直以为自己了解了引用传递,没想到再次打破了自己的认知,所以开一篇文章,来记录一下到目前所知(本人不敢说自己已经完全掌握了)。
从书中了解到,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)不变。
有疑问加站长微信联系(非本文作者)
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
关注微信4413 次点击
下一篇:Golang并发调度模型解析
添加一条新回复
(您需要 后才能回复 没有账号 ?)
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码` - 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传
收入到我管理的专栏 新建专栏
一直以为自己了解了引用传递,没想到再次打破了自己的认知,所以开一篇文章,来记录一下到目前所知(本人不敢说自己已经完全掌握了)。
从书中了解到,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)不变。