分享
  1. 首页
  2. 文章

理解Golang多重赋值

polar9527 · · 3206 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

个人主页

Golang 的多重赋值可以用于值交换操作

两个值可以方便的如下交换:

a, b = b, a

四个值同样可以如下交换

a, b, c, d = b, c, a, d

那这个交换底层是怎么实现的呢?
我们来做个试验,看看这一段四值交换 golang 代码的的汇编代码

func main(){
 a := 1
 b := 2
 c := 3
 d := 4
 a, b, c, d = b, c, a, d
}
$>dlv debug main.go
Type 'help' for list of commands.
(dlv) b main.main
Breakpoint 1 set at 0x454b6a for main.main() ~/pathToProject/main.go:3
(dlv) r
Process restarted with PID 26528
(dlv) c
> main.main() ~/pathToProject/main.go:3 (hits goroutine(1):1 total:1) (PC: 0x454b6a)
 1: package main
 2:
=> 3: func main() {
 4: a := 1
 5: b := 2
 6: c := 3
 7: d := 4
(dlv) disassemble
TEXT main.main(SB) D:/Users/polar/go/src/mylab/main.go
 main.go:3 0x454b50 65488b0c2528000000 mov rcx, qword ptr gs:[0x28]
 main.go:3 0x454b59 488b8900000000 mov rcx, qword ptr [rcx]
 main.go:3 0x454b60 483b6110 cmp rsp, qword ptr [rcx+0x10]
 main.go:3 0x454b64 0f8619020000 jbe 0x454d83
=> main.go:3 0x454b6a* 4883ec50 sub rsp, 0x50
 main.go:3 0x454b6e 48896c2448 mov qword ptr [rsp+0x48], rbp
 main.go:3 0x454b73 488d6c2448 lea rbp, ptr [rsp+0x48]
 main.go:4 0x454b78 48c744242801000000 mov qword ptr [rsp+0x28], 0x1 // a := 1
 main.go:5 0x454b81 48c744242002000000 mov qword ptr [rsp+0x20], 0x2 // b := 2
 main.go:6 0x454b8a 48c744241803000000 mov qword ptr [rsp+0x18], 0x3 // c := 3
 main.go:7 0x454b93 48c744241004000000 mov qword ptr [rsp+0x10], 0x4 // d := 4
 main.go:9 0x454b9c 488b442428 mov rax, qword ptr [rsp+0x28]
 main.go:9 0x454ba1 4889442440 mov qword ptr [rsp+0x40], rax // temp = a
 main.go:9 0x454ba6 488b442420 mov rax, qword ptr [rsp+0x20]
 main.go:9 0x454bab 4889442428 mov qword ptr [rsp+0x28], rax // a = b
 main.go:9 0x454bb0 488b442418 mov rax, qword ptr [rsp+0x18]
 main.go:9 0x454bb5 4889442420 mov qword ptr [rsp+0x20], rax // b = c
 main.go:9 0x454bba 488b442410 mov rax, qword ptr [rsp+0x10]
 main.go:9 0x454bbf 4889442418 mov qword ptr [rsp+0x18], rax // c = d
 main.go:9 0x454bc4 488b442440 mov rax, qword ptr [rsp+0x40]
 main.go:9 0x454bc9 4889442410 mov qword ptr [rsp+0x10], rax // d = temp

很好理解了,就是编译器帮我们在栈上创建了一个临时变量 temp, 然后按顺序交换其他各个变量的值。

那么下面这种情况,会发生什么呢?

a := 1
b := 2
a, b, a = b, a, b

a 和 b 最终的值是多少?

看一下汇编代码就清楚了

main.go:5 0x454b9b 48c744241801000000 mov qword ptr [rsp+0x18], 0x1 // a:=1
main.go:6 0x454ba4 48c744241002000000 mov qword ptr [rsp+0x10], 0x2 // b:=2
main.go:7 0x454bad 488b442418 mov rax, qword ptr [rsp+0x18]
main.go:7 0x454bb2 4889442428 mov qword ptr [rsp+0x28], rax // aTemp := a
main.go:7 0x454bb7 488b442410 mov rax, qword ptr [rsp+0x10]
main.go:7 0x454bbc 4889442420 mov qword ptr [rsp+0x20], rax // bTemp := b
main.go:7 0x454bc1 488b442410 mov rax, qword ptr [rsp+0x10]
main.go:7 0x454bc6 4889442418 mov qword ptr [rsp+0x18], rax // a = b
main.go:7 0x454bcb 488b442428 mov rax, qword ptr [rsp+0x28]
main.go:7 0x454bd0 4889442410 mov qword ptr [rsp+0x10], rax // b = aTemp
main.go:7 0x454bd5 488b442420 mov rax, qword ptr [rsp+0x20]
main.go:7 0x454bda 4889442418 mov qword ptr [rsp+0x18], rax // a = bTemp

相当于

aTemp = a
bTemp = b
a, b, a = bTemp, aTemp, bTemp

这里两个值交换的操作的原理是将两个被赋值的变量的值,都存储在临时变量里,然后再用临时变量去赋值。所以这个例子赋值顺序对结果是无影响的,其结果仍然是 a = 2, b = 1。

不用再像 C 语言那样写交换函数再内联了,相当于把脏活丢给编译器干了。

欢迎转载,请注明出处~
作者个人主页


有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:polar9527

查看原文:理解Golang多重赋值

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
3206 次点击 ∙ 2 赞
被以下专栏收入,发现更多相似内容
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏