Go 語言中的兩種 slice 運算式

來源:互聯網
上載者:User
在此之前,已經有許多關於 Golang 中 slice 的介紹,比如* [Go Slices: usage and internals](https://blog.golang.org/go-slices-usage-and-internals)* [How to avoid Go gotchas](https://blog.golang.org/go-slices-usage-and-internals)本文只是關注於 slice 的表示方式,它們可以建立兩種類型的值:* 截斷的 string* 指向 array 或者 slice 的指標Go 語言對 slice 有兩種表示方式:簡略運算式與完整運算式。## 簡略運算式Slice 的簡略運算式是:```goInput[low:high]```其中,low 和 high 是 slice 的索引(index),其數值必須是整數,它們指定了輸入運算元(Input)的哪些元素可以被放置在結果的 slice 中。輸入運算元可以是 string,array,或者是指向 array 或 slice 的指標。結果 slice 的長度就是 high-low。如下例所示:```gonumbers := [10]int{0,1,2,3,4,5,6,7,8,9}s := numbers[2:4:6]fmt.Println(s) // [2, 3]fmt.Println(cap(s)) // 4```將 slice 運算式應用到 array 的指標中,這是第一次取消對該指標的引用,然後以常規的方式應用 slice 運算式。將 slice 運算式應用於數組的指標,是先解引用該指標,然後按常規方式應用切片運算式的簡寫形式。```gonumbers := [5]int{1, 2, 3, 4, 5}fmt.Println((&numbers)[1:3]) // [2, 3]```Slice 的索引 low 和 high 可以省略,low 的預設值是0,high 的預設值為 slice 的長度:```gofmt.Println("foo"[:2]) // "fo"fmt.Println("foo"[1:]) // "oo"fmt.Println("foo"[:]) // "foo"```但是 slice 的索引不可以是以下幾種類型的值:* low < 0 or high < 0* low <= high* high <= len(input)```gofmt.Println("foo"[-1:]) // invalid slice index -1 (index must be non-negative)//fmt.Println("foo"[:4]) // invalid slice index 4 (out of bounds for 3-byte string)fmt.Println("foo"[2:2]) // ""(blank)//fmt.Println("foo"[2:1]) // invalid slice index: 2 > 1```否則,即使一個超過 slice 範圍的索引不能在編譯的時候被檢測到,那麼在運行時就會發生一個 panic。```gofunc low() int {return 4}func main() {fmt.Println("foo"[low():])}``````panic: runtime error: slice bounds out of rangegoroutine 1 [running]:panic(0x102280, 0x1040a018)/usr/local/go/src/runtime/panic.go:500 +0x720main.main()/tmp/sandbox685025974/main.go:12 +0x120```## 完整運算式這種方法可以控制結果 slice 的容量,但是只能用於 array 和指向 array 或 slice 的指標( string 不支援),在簡略運算式中結果 slice 的容量是從索引low開始的最大可能容量( slice 的簡略運算式):```gonumbers := [10]int{0,1,2,3,4,5,6,7,8,9}s := numbers[1:4]fmt.Println(s) // [1, 2, 3]fmt.Println(cap(s)) // 9```對於一個 array 來說,cap(a) == len(a) 在上面的程式碼片段中,s 的容量是 9,因為這個 slice 從索引 1 開始,而底層 array 有 8 個元素(2 到 9)。完整的 slice 運算式允許修改這種預設行為,以如下代碼為例:```gonumbers := [10]int{0,1,2,3,4,5,6,7,8,9}s := numbers[1:4:5]fmt.Println(s) // [1, 2, 3]fmt.Println(cap(s)) // 4```完整的 slice 運算式具有以下的形式:```goinput[low:high:max]```索引 low 和索引 high 的含義和工作方式與簡略運算式相同。唯一的區別是 max 將結果 slice 的容量設定為 max-low。```gonumbers := [10]int{0,1,2,3,4,5,6,7,8,9}s := numbers[2:4:6]fmt.Println(s) // [2, 3]fmt.Println(cap(s)) // 4```當 slice 的輸入運算元是一個 slice 時,結果 slice 的容量取決於輸入運算元,而不是它的指向的底層 array:```gonumbers := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}fmt.Println(cap(numbers)) // 10s1 := numbers[1:4]fmt.Println(s1) // [1, 2, 3]fmt.Println(cap(s1)) // 9s2 := numbers[1:4:5]fmt.Println(s2) // [1, 2, 3]fmt.Println(cap(s2)) // 4s3 := s2[:]fmt.Println(s3) // [1, 2, 3]fmt.Println(cap(s3)) // 4```這個例子中 s3 的容量不能超過 s2 的容量 (4),即使它指向的 array 有 10 個元素,而且 s1,s2,s3 都是從 1 開始的。當輸入運算元是 slice 時,完整運算式的索引 high 不能超過其 cap(input)```gonumbers := [10]int{0,1,2,3,4,5,6,7,8,9}s1 := numbers[0:1]fmt.Println(s1) // [0]fmt.Println(len(s1)) // 1fmt.Println(cap(s1)) // 10s2 := numbers[0:5]fmt.Println(s2) // [0, 1, 2, 3, 4]fmt.Println(cap(s1)) // 10```另外,對於它的 max 取值,有兩個額外的規則* high <= max* max <= cap(input)```gonumbers := [10]int{0,1,2,3,4,5,6,7,8,9}s1 := numbers[0:1]s2 := numbers[0:5:11] // invalid slice index 11 (out of bounds for 10-element array)fmt.Println(s1, s2)```在完整的 slice 運算式中低索引(low)是可以省略的```gonumbers := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}s := numbers[:4:6]fmt.Println(s) // [0, 1, 2, 3]fmt.Println(cap(s)) // 6```然而,不能省略略高索引(high)```gonumbers := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}s1 := numbers[:4:6]s2 := s1[::5]fmt.Println(s2)fmt.Println(cap(s2))```否則,代碼會在編譯時間報錯"middle index required in 3-index slice"

via: https://medium.com/golangspec/slice-expressions-in-go-963368c20765

作者:Michał Łowicki 譯者:bizky 校對:polaris1119

本文由 GCTT 原創編譯,Go語言中文網 榮譽推出

本文由 GCTT 原創翻譯,Go語言中文網 首發。也想加入譯者行列,為開源做一些自己的貢獻嗎?歡迎加入 GCTT!
翻譯工作和譯文發表僅用於學習和交流目的,翻譯工作遵照 CC-BY-NC-SA 協議規定,如果我們的工作有侵犯到您的權益,請及時聯絡我們。
歡迎遵照 CC-BY-NC-SA 協議規定 轉載,敬請在本文中標註並保留原文/譯文連結和作者/譯者等資訊。
文章僅代表作者的知識和看法,如有不同觀點,請樓下排隊吐槽

133 次點擊  
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.