亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

我可以使用單線從切片中的位置 n 彈出一個元素嗎?

我可以使用單線從切片中的位置 n 彈出一個元素嗎?

Go
HUH函數 2022-06-27 16:08:58
我正在瀏覽切片技巧文檔,看到一些單線彈出和彈出前面。例如,這兩個工作正常:// pops := []int{1, 2, 3}     last, s := s[len(s)-1], s[:len(s)-1]    fmt.Println(last, s) // Prints 3 [1 2]// pop fronts := []int{1, 2, 3}     first, s := s[0], s[1:]                 fmt.Println(first, s)  // Prints 1 [2 3]但是如果我嘗試做這樣的事情來彈出第二個元素:s := []int{1, 2, 3}     second, s := s[1], append(s[0:1], s[2:]...)fmt.Println(second, s) // Prints 3 [1 3]它彈出第二個元素,但second變量指向新切片中的第二個元素。為什么在這種情況下會發生這種情況,而前兩個情況卻沒有?為了工作,我必須使用單獨的行:s := []int{1, 2, 3}                     second := s[1]          s = append(s[0:1], s[2:]...)fmt.Println(second, s) // Prints 2 [1 3]
查看完整描述

1 回答

?
慕森卡

TA貢獻1806條經驗 獲得超8個贊

Go 規范中關于 assignments的部分告訴我們,這是

第二種形式

元組賦值。它接著說:

任務分兩個階段進行。首先,左側的索引表達式指針間接(包括選擇器中的隱式指針間接)的操作數和右側的表達式都按通常的順序進行計算。其次,作業是按從左到右的順序進行的。

因此,編譯器計算seconds通過評估它們來進行賦值——這只是產生它們的名稱,或多或少1——并且還評估右側的表達式

通常的順序

這意味著我們必須通過鏈接查看“通常的順序”是什么意思。這使我們得到評估順序

這里的文字有點棘手,但這個例子很有啟發性:

在(函數局部)賦值中

y[f()], ok = g(h(), i()+x[j()], <-c), k()

f()函數調用和通信按, h()i()j()<-cg(), 和的順序發生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,這些都變成了對變量的賦值,但最終結果都是一樣的。

2append函數決定是進行就地修改還是創建新的后備數組。但是,在這種情況下,由于我們正在縮小總長度,這顯然是可能的,并且實際實現每次都會利用這一點——盡管也沒有具體說明!


結論

這里要做的事情是編寫一個執行提取和更新的小函數,而不是作為單行程序,并簡單地允許編譯器將其內聯成相當快的東西。當然,這使我們希望使用泛型,因此希望使用 Go 2。


查看完整回答
反對 回復 2022-06-27
  • 1 回答
  • 0 關注
  • 107 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號