1 回答

TA貢獻1806條經驗 獲得超8個贊
Go 規范中關于 assignments的部分告訴我們,這是
第二種形式
元組賦值。它接著說:
任務分兩個階段進行。首先,左側的索引表達式和指針間接(包括選擇器中的隱式指針間接)的操作數和右側的表達式都按通常的順序進行計算。其次,作業是按從左到右的順序進行的。
因此,編譯器計算second
并s
通過評估它們來進行賦值——這只是產生它們的名稱,或多或少1——并且還評估右側的表達式
通常的順序
這意味著我們必須通過鏈接查看“通常的順序”是什么意思。這使我們得到評估順序。
這里的文字有點棘手,但這個例子很有啟發性:
在(函數局部)賦值中
y[f()], ok = g(h(), i()+x[j()], <-c), k()
f()
函數調用和通信按,h()
,i()
,j()
,<-c
,g()
, 和的順序發生k()
。然而,這些事件與評估和索引x
以及評估相比的順序y
沒有指定。
讓我們將其與您自己的表達式進行比較:
second, s := s[1], append(s[0:1], s[2:]...)
我們知道append
它將在之前被調用......好吧,我們不太確定:沒有進一步的(調用權)函數調用或通道調用。s
但顯然它必須在被分配之前被調用。
但是,與此同時,此調用相對于“評估和索引”的順序s[1]
并未明確指定。如果先完成,該append
操作將(可能是2 次)就地修改支持 slice 的數組s[0:1]
。
那么,顯然正在發生的事情append(s[0:1], s[2:]...)
實際上是在原地修改數組。然后進行評估和索引s[1]
,修改數組。這會獲取 的修改后的值s[1]
并將其復制到變量second
。
為什么在這種情況下會發生這種情況,而前兩個情況卻沒有?
那些不會調用append
,因此不允許append
就地修改數組。
1由于在內部使用了 SSA,這些都變成了對新變量的賦值,但最終結果都是一樣的。
2由append
函數決定是進行就地修改還是創建新的后備數組。但是,在這種情況下,由于我們正在縮小總長度,這顯然是可能的,并且實際實現每次都會利用這一點——盡管也沒有具體說明!
結論
這里要做的事情是編寫一個執行提取和更新的小函數,而不是作為單行程序,并簡單地允許編譯器將其內聯成相當快的東西。當然,這使我們希望使用泛型,因此希望使用 Go 2。
- 1 回答
- 0 關注
- 107 瀏覽
添加回答
舉報