lf215
lf215

Reputation: 1009

Why does go allow slicing from len(slice)?

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

Executable example

Upvotes: 3

Views: 351

Answers (3)

icza
icza

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 capacity cap(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

Denys S&#233;guret
Denys S&#233;guret

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

Tagir Valeev
Tagir Valeev

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

Related Questions