The golang blog states :
"A slice can also be formed by "slicing" an existing slice or array. Slicing is done by specifying a half-open range with two indices separated by a colon. For example, the expression b[1:4] creates a slice including elements 1 through 3 of b (the indices of the resulting slice will be 0 through 2)."
Can someone please explain to me the logic in the above. IE. Why doesn't b[1:4] reference elements 1 through 4? Is this consistent with other array referencing?
The reason is given in the Go Language Specification section on Slices.
For a string, array, or slice a, the primary expression
a[low : high]
constructs a substring or slice. The index expressions low and high select which elements appear in the result. The result has indexes starting at 0 and length equal to high - low.
For convenience, any of the index expressions may be omitted. A missing low index defaults to zero; a missing high index defaults to the length of the sliced operand.
It's easy and efficient to calculate the length of the slice as high - low.
Go uses half-open intervals for slices like many other languages. In a more mathematical notation, the slice b[1:4]
is the interval [1,4)
which excludes the upper endpoint.
Half-open intervals make sense for many reasons, when you get down to it. For instance, with a half-open interval like this, the number of elements is:
n = end - start
which is a pretty nice and easy formula. For a closed interval, it would be:
n = (end - start) + 1
which is (not a lot, but still) more complicated.
It also means that for e.g. a string, the entire string is [1, len(s)]
which also seems intuitive. If the interval was closed, to get the entire string you would need [1, len(s) + 1]
.
Indexes point to the "start" of the element. This is shared by all languages using zero-based indexing:
| 0 | first | 1 | second | 2 | third | 3 | fourth | 4 | fifth | 5 |
[0] = ^
[0:1] = ^ --------> ^
[1:4] = ^-------------------------------------> ^
[0:5] = ^ ----------------------------------------------------------> ^
It's also common to support negative indexing, although Go doesn't allow this:
|-6 | |-5 | |-4 | |-3 | |-2 | |-1 |
| 0 | first | 1 | second | 2 | third | 3 | fourth | 4 | fifth | 5 |