Reading an element
You read an element of a slice exactly as you read one from an array: the name of the slice, then the index in square brackets. Indexing is zero-based, so the first element is at index 0.
array := []int{50, 60, 70}
fmt.Println(array[0])
data := array[1]
fmt.Println(data)
50
60
The expression array[1] has the slice's element type, here int. That means you can print it, store it in a new variable as data does above, or use it in arithmetic. Reading an element does not change the slice.
The lesson names its variable array, but the value is a slice: the literal has nothing between the brackets. Go does not reserve the word array, so the name is legal, although a name like nums would say more.
Valid indices
A slice with n elements has the valid indices 0 to n - 1. Anything else is out of range. Unlike an array, a slice can change length while the program runs, so Go checks the index when the line executes. Asking for an index that does not exist stops the program with a panic, which has its own lesson.
The last element of a slice is at len(s) - 1. Go has no negative indices, so you cannot write s[-1] to reach the end.
The exercise
The lesson gives you these two slices:
fruits := []string{"mango", "kiwi", "grapefruit"}
ages := []int{14, 32, 50, 21}
You print three things with fmt.Println.
Step 1: the second fruit
The second item is at index 1, because counting starts at 0. Index 2 would give grapefruit, the third item.
Step 2: the sum of the first three ages
The first three ages are at indices 0, 1 and 2. Add them inside the call. Go evaluates the whole expression first and hands the finished number to Println, so the output is the single value 96.
Step 3: last minus first
The slice holds four numbers, so the last one is at index 3. Subtract the element at index 0 from it.
fmt.Println(fruits[1])
fmt.Println(ages[0] + ages[1] + ages[2])
fmt.Println(ages[3] - ages[0])
kiwi
96
7
Reading in a loop
Hard-coded indices are fine for a few lookups. To visit every element, let a loop produce the index:
sum := 0
for i := 0; i < len(ages); i++ {
sum += ages[i]
}
fmt.Println(sum)
117
The condition is i < len(ages), not <=, because the last valid index is one less than the length.
Using range
When you only need the values, range hands you each one without any index arithmetic, so there is no way to step past the end:
for _, age := range ages {
fmt.Println(age)
}
The loop prints 14, 32, 50 and 21, each on its own line. The blank identifier _ discards the index, which Go requires you to do explicitly, since an unused variable is a compile error. Writing age gives you a copy of the element: changing it inside the loop does not change the slice.
Common mistakes
- Off-by-one from counting at 1. The second element is
s[1]. - Indexing with the length.
ages[len(ages)]compiles, but it fails when it runs, because the last valid index islen(ages) - 1. - Reading from an empty slice. An empty slice has no valid index at all, so even
s[0]panics. Checklen(s) > 0first when the slice might be empty. - Using a non-integer index. An index must be an integer, not a string and not a floating-point number.
Key takeaways
- Use
s[i]to read an element; the first index is 0. - Valid indices run from 0 to
len(s) - 1, and Go checks them while the program runs. - An element is a normal value, so use it directly in expressions and calls.
- Reach the end of a slice with
len(s) - 1, not with a negative index.