为什么要允许从len(切片)切片?

时间:2015-05-13 07:19:17

标签: arrays go 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

3 个答案:

答案 0 :(得分:4)

引用Spec: Slice Expressions

  

对于数组或字符串,如果0 <= low <= high <= len(a),则索引在范围中,否则它们超出范围。对于切片,上部索引边界是切片容量cap(a)而不是长度。

因此规范允许使用底层数组len(a)索引,len(a) 包含(或cap(a) in切片的情况,在这种情况下具有相同的值)。这就是为什么a[3:]在你的情况下不会出现恐慌。

但它当然会产生空白,因为:

a[low : high]

表示结果的索引从0开始,长度等于high - low,并且由于high被省略,因此默认为len(a) len(a) - len(a) = 0。< / p>

并且(根据规范)使用索引> len(a) 将超出范围因此导致运行时恐慌:

  

如果索引在运行时超出范围,则会发生run-time panic

答案 1 :(得分: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]

另一方面,负长度的切片不一致。它没有任何意义,因而被禁止。

答案 2 :(得分: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));

只有最后一个语句失败。