Skip to main content

Retrieving Single Elements

This lesson shows how to get one element out of a slice: by its position, by a condition, or at random. It also shows how to check whether an element exists at all.

Go has no null. When a lookup can fail, a Go function returns two values: the element and a bool called ok. This is the same value, ok pattern you know from maps.

Reading a position that does not exist, such as words[5] in a slice of 5 elements, stops the program with a panic (a runtime error). So we always check len() first.

Other languages have many ready-made functions for this. Go keeps the language small: you use square brackets, the slices package, or a small helper function you write once.


Retrieve by Position

Every element in a slice has a position called an index. The first index is 0, so the last one is len(words)-1.

To read an element by position, write the index inside square brackets: words[3]. This is Go's way of reading the element at a position, the first one, or the last one.

Go has no elementAtOrNull() or elementAtOrElse(). A small generic helper checks the index against len() and returns either value, ok or the result of a fallback function. This way an out-of-range index cannot panic.

Element at a position

words[3] reads the element at index 3. Since counting starts at 0, that is the fourth word.

Prompt
Make a slice with the words one, two, three, four, five. Print the element at index 3 using square brackets.
Output: Go program and captured output
Element at a position

First and last element

The first element is words[0]. The last one is words[len(words)-1], because the length is 5 but the last index is 4.

Prompt
Make a slice with the words one, two, three, four, five. Print the first element with index 0, then the last element with index len minus 1.
Output: Go program and captured output
First and last element

Element at a position, or ok == false

ElementAt checks the index against len(). Index 1 is in range, so it returns "two" and true. Index 5 is out of range, so it returns the zero value "" and false instead of panicking.

Prompt
Write a generic ElementAt helper that returns the element at an index and true, or the zero value and false when the index is out of range. Call it on the words one, two, three, four, five with index 1 and with index 5, and print the value in quotes together with the ok flag.
Output: Go program and captured output
Element at a position, or ok == false

Element at a position, or a fallback

ElementAtOrElse takes a fallback function. The function receives the index, so it can build a message like "The value for index 5 is undefined".

Prompt
Write a generic ElementAtOrElse helper that returns the element at an index, or the result of a fallback function that receives the index. Call it on the words one, two, three, four, five with index 5 and a fallback that builds the text "The value for index 5 is undefined". Print the result.
Output: Go program and captured output
Element at a position, or a fallback

Retrieve by Condition

Often you do not know the position. You know a condition instead: the first word longer than 3 letters, the last word that starts with "f". The condition is a function that takes one element and returns true or false.

For the first match, the slices package has slices.IndexFunc(). It returns the index of the first element that passes the test, or -1 when nothing does. You then read the element with that index.

There is no last-match function in slices. A for loop that counts down from len(words)-1 finds the last match: the first hit while walking backwards is the last one in the slice.

Go has no ready-made find functions beyond that. Small generic helpers Find and FindLast do the job and return value, ok, so "nothing matched" is just ok == false.

First match

slices.IndexFunc() gives the index of the first word with len(s) > 3. That word is "three".

Prompt
Make a slice with the words one, two, three, four, five. Use slices.IndexFunc to find the first word longer than 3 letters and print that word.
Output: Go program and captured output
First match

Last match

The loop starts at the last index and moves down. The first word it meets that starts with "f" is "five", so the loop prints it and stops with break.

Prompt
Make a slice with the words one, two, three, four, five. Loop backwards from the last index and print the first word that starts with "f", then stop the loop.
Output: Go program and captured output
Last match

First match, or ok == false

No word is longer than 6 letters, so Find returns ok == false and the program prints "not found". In the numbers slice the first even number is 2.

Prompt
Write a generic Find helper that returns the first element passing a condition and true, or the zero value and false. On the words one, two, three, four, five search for a word longer than 6 letters and print "not found" when ok is false. Then search the numbers 1, 2, 3, 4 for the first even number and print it.
Output: Go program and captured output
First match, or ok == false

Last match, or ok == false

FindLast walks the numbers backwards. The last even number is 4, and it is found right away.

Prompt
Write a generic FindLast helper that walks a slice backwards and returns the last element passing a condition and true, or the zero value and false. Use it on the numbers 1, 2, 3, 4 to find the last even number and print it.
Output: Go program and captured output
Last match, or ok == false

Retrieve with Selector

Sometimes you want to change each element first and then take the first result that fits.

Go has no such function. A for loop does it: convert each element, test the result, and break at the first good one. The slice here has type []any, so it can hold a number, a string and a bool at the same time. fmt.Sprint() turns any value into text.

First converted value that fits

Each value is turned into text with fmt.Sprint(). 0 becomes "0", which is too short. "true" has 4 characters, so it is printed and the loop stops.

Prompt
Make a slice of type []any holding 0, the string "true" and false. Turn each value into text with fmt.Sprint and print the first text that has 4 or more characters, then stop.
Output: Go program and captured output
First converted value that fits

Random Element

To pick a random element, pick a random index. The math/rand package gives random numbers; r.Intn(n) returns a number from 0 up to n-1, which is exactly the range of valid indexes.

Go has no random() method on slices, so the index goes into square brackets as usual.

A random source made with rand.NewSource(42) starts from a fixed seed. With the same seed the program picks the same element every time, which makes the output predictable. Leave out the seed when you want a different result on each run.

Pick a random element

With seed 42 the source picks index 1, so the program prints 2. Change the seed and a different number can come out.

Prompt
Make a slice with the numbers 1, 2, 3, 4. Create a random source seeded with 42 using math/rand, pick a random index with Intn and print the element at that index.
Output: Go program and captured output
Pick a random element

Check Element Existence

To check whether a value is in a slice, use slices.Contains(). It returns true or false.

Go has no containsAll(). A small generic helper loops over the wanted values and calls slices.Contains() for each one. It returns false as soon as one value is missing.

Go also has no isEmpty() or isNotEmpty(). Compare the length: len(s) == 0 means empty, len(s) > 0 means not empty.

Contains one value

"four" is in the slice, so the first check is true. "zero" is not, so the second check is false.

Prompt
Make a slice with the words one, two, three, four, five. Use slices.Contains to check whether "four" is in the slice and whether "zero" is in the slice. Print both answers.
Output: Go program and captured output
Contains one value

Contains all values

Both "four" and "one" are in the slice, so ContainsAll returns true. "zero" is missing, so the second call returns false.

Prompt
Write a generic ContainsAll helper that returns true only when every value of a second slice is found in the first slice, using slices.Contains. Check the words one, two, three, four, five for four and one, then for one and zero. Print both answers.
Output: Go program and captured output
Contains all values

Empty or not empty

empty has length 0, so len(empty) == 0 is true. words has 5 elements, so len(words) > 0 is also true.

Prompt
Make a slice with the words one, two, three, four, five and an empty string slice. Print whether the length of the empty slice is 0, then whether the length of the words slice is greater than 0.
Output: Go program and captured output
Empty or not empty