1. 程式人生 > 其它 >【Golang】遇到的有趣的Go賦值問題並附帶以下不負責任的解析

【Golang】遇到的有趣的Go賦值問題並附帶以下不負責任的解析

技術標籤:Golang不負責任解析日常研究golang

今天在做一道題的時候發現了這麼一個有趣的題目:

func main() {
	index := 1
	a := []string{"f", "ff", "fff"}
	index, a[index-1] = 88888, "ffff"
	fmt.Println(a)
}

這個輸出是什麼呢?我第一眼看的時候感覺會輸出panic,因為下標超界,但是執行之後發現沒這麼簡單,執行結果如下
在這裡插入圖片描述
執行之後我驚了,不知道為什麼會這樣,然後我就輸出了彙編看了一下(去掉了一些多餘的彙編程式碼,我們只看賦值那行的彙編):

本篇文章基於go1.15+版本以及mac os 作業系統

//把index的值複製到DX暫存器中
0x00f2 00242 MOVQ    "".index+48(SP), DX 
 // DX暫存器的值-1 在此能看出是先對其進行了-1
0x00f7 00247 DECQ    DX 
// 把DX暫存器裡的值複製autotmp_4+56這個地址上
0x00fa 00250 MOVQ    DX, ""..autotmp_4+56(SP) 
// 把88888賦值給index+48地址即賦值88888給index
0x00ff 00255 MOVQ    $88888, "".index+
48(SP) // 把剛才-1了的值放在AX暫存器中 0x0108 00264 MOVQ ""..autotmp_4+56(SP), AX // 把a就是那個陣列的偏移104個地址的值放入DX暫存器 0x010d 00269 MOVQ "".a+104(SP), DX // 把a就是那個陣列的偏移112個地址的值放入DX暫存器 0x0112 00274 MOVQ "".a+112(SP), CX // 比較AX暫存器和CX暫存器 0x0117 00279 CMPQ AX, CX // 如果沒溢位就跳到293 0x011a 00282 JCS 293 // 否則 0x011c 00284
NOP // 跳到605 0x0120 00288 JMP 605 // 邏輯移位(好像是) 0x0125 00293 SHLQ $4, AX // 把DX的AX*1的地址給CX Ax就是被-1後的那個值存放的地方 0x0129 00297 LEAQ (DX)(AX*1), CX 0x012d 00301 LEAQ 8(CX), CX 0x0131 00305 MOVQ $4, (CX) // 反正就是之前做了一堆複製和傳地址操作把DX的AX*1的地址給了DI 0x0138 00312 LEAQ (DX)(AX*1), DI ····· // 把ffff這個字串放到AX暫存器內 0x014a 00330 LEAQ go.string."ffff"(SB), AX // 從AX暫存器複製出ffff複製到DI就是要修改的陣列的那個位置 0x0151 00337 MOVQ AX, (DI)

大概就是這樣,其實最根本的原因就是

index-1這個操作早於給index賦值這個操作,並且提前將其放到了某塊地址中所以後續的陣列下標賦值操作是根據這個放在某個地址中的index-1的值進行的賦值。

作者對彙編不甚瞭解,如果哪裡有錯誤請大佬指正。