理解Golang多重賦值
個人主頁 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 語言那樣寫交換函式再內聯了,相當於把髒活丟給編譯器幹了。
歡迎轉載,請註明出處~ 作者個人主頁
相關文章
- 整明白 Golang struct 例項化和賦值GolangStruct賦值
- golang 實現多型的賦值問題Golang多型賦值
- 深入理解PHP中賦值與引用PHP賦值
- Golang Map實現(四) map 的賦值和擴容Golang賦值
- JS中的變數賦值深入理解JS變數賦值
- 自己對Java中if變數賦值的理解Java變數賦值
- 你真的理解js的賦值語句麼JS賦值
- [譯] 使用多重賦值與元組解包提升 Python 程式碼的可讀性賦值Python
- 【c++】深賦值與淺賦值C++賦值
- php之普通變數賦值、物件賦值、引用賦值的區別PHP變數賦值物件
- 你真的理解Python中的賦值、傳參嗎?Python賦值
- 變數的賦值 指標間接賦值變數賦值指標
- 常被新手忽略的值賦值和引用賦值(偏redux向)賦值Redux
- Verilog連續賦值、過程賦值、過程連續賦值總結賦值
- javascript變數賦值或者重新賦值注意事項JavaScript變數賦值
- 陣列賦值陣列賦值
- 解構賦值賦值
- PLSQL Language Reference-PL/SQL語言基礎-變數賦值-使用賦值語句賦值SQL變數賦值
- java裡面給物件賦值,慎用賦值符號(=) (轉)Java物件賦值符號
- golang const 宣告常量量時候,只寫名字,就會自動有值?——>[批量賦值][列舉]Golang賦值
- JS解構賦值JS賦值
- JavaScript 連等賦值JavaScript賦值
- 物件賦值轉換物件賦值
- CSS 屬性賦值CSS賦值
- php 自增賦值PHP賦值
- 賦值運算子(轉)賦值
- jquery取值和賦值(包含部分是原生js的取值和賦值)jQuery賦值JS
- 列表切片賦值給另一個變數,淺拷貝原理解析賦值變數
- vector訪問與賦值賦值
- vue scrollTop 無法賦值Vue賦值
- 使用反射為特性賦值反射賦值
- JavaScript 字串解構賦值JavaScript字串賦值
- JavaScript 物件解構賦值JavaScript物件賦值
- 運算子-賦值運算子賦值
- Makefile中幾種賦值(= := ?= +=)賦值
- If-Let 賦值運算子賦值
- Javascript 解構賦值,將屬性/值從物件/陣列中取出,賦值給其他變數JavaScript賦值物件陣列變數
- (12)非阻塞賦值與阻塞賦值區別(以簡單例子說明)賦值單例