Перейти к основному содержимому

Получение отдельных элементов

В этом уроке показано, как получить один элемент из слайса: по его позиции, по условию или случайно. Также показано, как проверить, существует ли элемент вообще.

В Go нет null. Когда поиск может не дать результата, функция в Go возвращает два значения: элемент и bool с именем ok. Это тот же шаблон value, ok, который вы знаете по map.

Чтение позиции, которой не существует, например words[5] в слайсе из 5 элементов, останавливает программу паникой (ошибкой во время выполнения). Поэтому мы всегда сначала проверяем len().

В других языках для этого есть много готовых функций. Go остаётся небольшим языком: вы используете квадратные скобки, пакет slices или маленькую вспомогательную функцию, которую пишете один раз.


Получение по позиции

У каждого элемента слайса есть позиция, которая называется индекс. Первый индекс — 0, поэтому последний — len(words)-1.

Чтобы прочитать элемент по позиции, напишите индекс в квадратных скобках: words[3]. Именно так в Go читают элемент на нужной позиции, первый элемент или последний.

В Go нет elementAtOrNull() или elementAtOrElse(). Маленькая обобщённая вспомогательная функция сравнивает индекс с len() и возвращает либо value, ok, либо результат запасной функции. Так индекс вне диапазона не может вызвать панику.

Элемент на позиции

words[3] читает элемент с индексом 3. Так как счёт начинается с 0, это четвёртое слово.

Prompt
Создайте слайс со словами one, two, three, four, five. Напечатайте элемент с индексом 3, используя квадратные скобки.
Вывод: программа на Go и захваченный вывод
Element at a position

Первый и последний элемент

Первый элемент — это words[0]. Последний — words[len(words)-1], потому что длина равна 5, а последний индекс — 4.

Prompt
Создайте слайс со словами one, two, three, four, five. Напечатайте первый элемент по индексу 0, затем последний элемент по индексу len минус 1.
Вывод: программа на Go и захваченный вывод
First and last element

Элемент на позиции или ok == false

ElementAt сравнивает индекс с len(). Индекс 1 находится в диапазоне, поэтому функция возвращает "two" и true. Индекс 5 вне диапазона, поэтому вместо паники она возвращает нулевое значение "" и false.

Prompt
Напишите обобщённую вспомогательную функцию ElementAt, которая возвращает элемент по индексу и true либо нулевое значение и false, когда индекс вне диапазона. Вызовите её на словах one, two, three, four, five с индексом 1 и с индексом 5 и напечатайте значение в кавычках вместе с флагом ok.
Вывод: программа на Go и захваченный вывод
Element at a position, or ok == false

Элемент на позиции или запасное значение

ElementAtOrElse принимает запасную функцию. Эта функция получает индекс, поэтому может построить сообщение вроде «Значение по индексу 5 не определено».

Prompt
Напишите обобщённую вспомогательную функцию ElementAtOrElse, которая возвращает элемент по индексу или результат запасной функции, получающей этот индекс. Вызовите её на словах one, two, three, four, five с индексом 5 и с запасной функцией, которая строит текст «Значение по индексу 5 не определено». Напечатайте результат.
Вывод: программа на Go и захваченный вывод
Element at a position, or a fallback

Получение по условию

Часто позиция вам неизвестна. Вместо неё известно условие: первое слово длиннее 3 букв, последнее слово, которое начинается с «f». Условие — это функция, которая принимает один элемент и возвращает true или false.

Для первого совпадения в пакете slices есть slices.IndexFunc(). Она возвращает индекс первого элемента, который проходит проверку, или -1, если такого элемента нет. Затем вы читаете элемент по этому индексу.

Функции для последнего совпадения в slices нет. Цикл for, который идёт вниз от len(words)-1, находит последнее совпадение: первое попадание при движении назад и есть последнее в слайсе.

Других готовых функций поиска в Go нет. Маленькие обобщённые вспомогательные функции Find и FindLast справляются с этой задачей и возвращают value, ok, поэтому «ничего не совпало» — это просто ok == false.

Первое совпадение

slices.IndexFunc() даёт индекс первого слова, для которого len(s) > 3. Это слово — "three".

Prompt
Создайте слайс со словами one, two, three, four, five. С помощью slices.IndexFunc найдите первое слово длиннее 3 букв и напечатайте это слово.
Вывод: программа на Go и захваченный вывод
First match

Последнее совпадение

Цикл начинается с последнего индекса и идёт вниз. Первое встреченное слово, которое начинается с "f", — это "five", поэтому цикл печатает его и останавливается через break.

Prompt
Создайте слайс со словами one, two, three, four, five. Пройдите циклом назад от последнего индекса и напечатайте первое слово, которое начинается с «f», затем остановите цикл.
Вывод: программа на Go и захваченный вывод
Last match

Первое совпадение или ok == false

Ни одно слово не длиннее 6 букв, поэтому Find возвращает ok == false и программа печатает «не найдено». В слайсе чисел первое чётное число — 2.

Prompt
Напишите обобщённую вспомогательную функцию Find, которая возвращает первый элемент, проходящий условие, и true либо нулевое значение и false. На словах one, two, three, four, five найдите слово длиннее 6 букв и напечатайте «не найдено», когда ok равно false. Затем найдите в числах 1, 2, 3, 4 первое чётное число и напечатайте его.
Вывод: программа на Go и захваченный вывод
First match, or ok == false

Последнее совпадение или ok == false

FindLast идёт по числам с конца. Последнее чётное число — 4, и оно находится сразу же.

Prompt
Напишите обобщённую вспомогательную функцию FindLast, которая идёт по слайсу с конца и возвращает последний элемент, проходящий условие, и true либо нулевое значение и false. Используйте её на числах 1, 2, 3, 4, чтобы найти последнее чётное число, и напечатайте его.
Вывод: программа на Go и захваченный вывод
Last match, or ok == false

Получение через селектор

Иногда нужно сначала изменить каждый элемент, а затем взять первый подходящий результат.

В Go такой функции нет. Это делает цикл for: преобразуйте каждый элемент, проверьте результат и сделайте break на первом подходящем. Слайс здесь имеет тип []any, поэтому может хранить одновременно число, строку и bool. fmt.Sprint() превращает любое значение в текст.

Первое подходящее преобразованное значение

Каждое значение превращается в текст с помощью fmt.Sprint(). 0 становится "0", и это слишком коротко. В "true" 4 символа, поэтому оно печатается и цикл останавливается.

Prompt
Создайте слайс типа []any, содержащий 0, строку «true» и false. Превратите каждое значение в текст с помощью fmt.Sprint и напечатайте первый текст, в котором 4 или более символов, затем остановитесь.
Вывод: программа на Go и захваченный вывод
First converted value that fits

Случайный элемент

Чтобы выбрать случайный элемент, выберите случайный индекс. Пакет math/rand даёт случайные числа; r.Intn(n) возвращает число от 0 до n-1, а это как раз диапазон допустимых индексов.

В Go у слайсов нет метода random(), поэтому индекс, как обычно, пишется в квадратных скобках.

Источник случайных чисел, созданный через rand.NewSource(42), начинает работу с фиксированного зерна (seed). С одним и тем же зерном программа каждый раз выбирает один и тот же элемент, и вывод становится предсказуемым. Не задавайте зерно, если хотите получать разный результат при каждом запуске.

Выбор случайного элемента

С зерном 42 источник выбирает индекс 1, поэтому программа печатает 2. Измените зерно — и может получиться другое число.

Prompt
Создайте слайс с числами 1, 2, 3, 4. Создайте источник случайных чисел с зерном 42 с помощью math/rand, выберите случайный индекс с Intn и напечатайте элемент по этому индексу.
Вывод: программа на Go и захваченный вывод
Pick a random element

Проверка наличия элемента

Чтобы проверить, есть ли значение в слайсе, используйте slices.Contains(). Она возвращает true или false.

В Go нет containsAll(). Маленькая обобщённая вспомогательная функция проходит по нужным значениям и вызывает slices.Contains() для каждого из них. Она возвращает false, как только одного значения не хватает.

В Go также нет isEmpty() или isNotEmpty(). Сравнивайте длину: len(s) == 0 означает «пусто», а len(s) > 0 означает «не пусто».

Содержит одно значение

"four" есть в слайсе, поэтому первая проверка даёт true. "zero" в слайсе нет, поэтому вторая проверка даёт false.

Prompt
Создайте слайс со словами one, two, three, four, five. С помощью slices.Contains проверьте, есть ли в слайсе «four» и есть ли «zero». Напечатайте оба ответа.
Вывод: программа на Go и захваченный вывод
Contains one value

Содержит все значения

И "four", и "one" есть в слайсе, поэтому ContainsAll возвращает true. "zero" отсутствует, поэтому второй вызов возвращает false.

Prompt
Напишите обобщённую вспомогательную функцию ContainsAll, которая возвращает true только тогда, когда каждое значение второго слайса есть в первом слайсе, используя slices.Contains. Проверьте слова one, two, three, four, five на наличие four и one, а затем one и zero. Напечатайте оба ответа.
Вывод: программа на Go и захваченный вывод
Contains all values

Пустой или не пустой

У empty длина 0, поэтому len(empty) == 0 — это true. В words 5 элементов, поэтому len(words) > 0 — тоже true.

Prompt
Создайте слайс со словами one, two, three, four, five и пустой слайс строк. Напечатайте, равна ли длина пустого слайса 0, а затем больше ли длина слайса слов, чем 0.
Вывод: программа на Go и захваченный вывод
Empty or not empty