2015-05-13 46 views
2

爲什麼下列行爲發生:爲什麼要允許從len(slice)切片?

a := []int{1, 2, 3} 
fmt.Println(a[0:]) 
fmt.Println(a[1:]) 
fmt.Println(a[2:]) 
fmt.Println(a[3:])// doesn't panic - why?? 
fmt.Println(a[4:])// panics as expected 

Executable example

+0

我應該更清楚這一點。我明白從規格來看這種行爲是可以預料的。但是從程序員的角度來看,似乎應該在約束中添加低 lf215

回答

3

a[3:]建立一個空的切片其中,就像一個空數組,是一個有效的和有用的對象(在所有的語言,而不僅僅是在Go) 。

空切片也仍然指向底層陣列,位置和能力,有時被擴展:

a := []int{1, 2, 3} 
emptySlice := a[1:1] 
fmt.Println(emptySlice) // [] 
notEmpty := emptySlice[0:2] 
fmt.Println(notEmpty) // [2 3] 

在另一端,具有負長度的切片是不一致的。這意味着什麼,因此被禁止。

1

因爲在切片中有0元素(3-3)是完全有效的。然而有-1元素(3-4)不是。

這樣的行爲也與其他語言一致。例如,Java:

System.out.println(Arrays.asList(1, 2, 3).subList(0, 3)); 
System.out.println(Arrays.asList(1, 2, 3).subList(1, 3)); 
System.out.println(Arrays.asList(1, 2, 3).subList(2, 3)); 
System.out.println(Arrays.asList(1, 2, 3).subList(3, 3)); 
System.out.println(Arrays.asList(1, 2, 3).subList(4, 3)); 

只有最後一條語句失敗。

4

Spec: Slice Expressions引用:

對於數組或字符串,指數在範圍內如果0 <= low <= high <= len(a),否則它們是超出範圍。對於切片,索引上限是切片容量cap(a)而不是長度。

所以規範允許(在在這種情況下具有相同的值的切片的情況下,或cap(a))使用索引到底層陣列len(a)包括len(a)。這就是爲什麼a[3:]在你的情況下不會恐慌。

但它會產生當然空片,這是因爲:

a[low : high] 

意味着結果具有起始於0等於high - low指數和長度,並且自high被省略,則默認爲len(a)因此len(a) - len(a) = 0

並且還使用索引> len(a)將超出範圍並因此導致一個在運行恐慌(根據頻譜):

如果索引超出範圍在運行時,一個run-time panic發生。