Reputation: 1009
Why does the following behavior occur:
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
Upvotes: 3
Views: 351
Reputation: 417512
Quoting from the Spec: Slice Expressions:
For arrays or strings, the indices are in range if
0 <= low <= high <= len(a)
, otherwise they are out of range. For slices, the upper index bound is the slice capacitycap(a)
rather than the length.
So the specification allows to use indices up to len(a)
of the underlying array, len(a)
included (or cap(a)
in case of a slice which in this case has the same value). That's why a[3:]
in your case doesn't panic.
But it will yield an empty slice of course, because:
a[low : high]
means the result has indices starting at 0
and length equal to high - low
and since high
is omitted, it defaults to len(a)
therefore len(a) - len(a) = 0
.
And also (according to the spec) using an index > len(a)
will be out of range and therefore cause a runtime panic:
If the indices are out of range at run time, a run-time panic occurs.
Upvotes: 7
Reputation: 382102
a[3:]
builds an empty slice which, just like an empty array, is a valid and useful object (in all languages, not just in Go).
An empty slice also still points to an underlying array, a position and a capacity and can sometimes be extended:
a := []int{1, 2, 3}
emptySlice := a[1:1]
fmt.Println(emptySlice) // []
notEmpty := emptySlice[0:2]
fmt.Println(notEmpty) // [2 3]
On the other end, a slice with a negative length is inconsistent. It means nothing and thus is forbidden.
Upvotes: 3
Reputation: 100169
Because having 0
elements (3-3
) in the slice is perfectly valid. However having -1
element (3-4
) is not.
Such behavior is also consistent with other languages. For example, 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));
Only the last statement fails.
Upvotes: 2