Массивы и срезы: создание, индексирование, len, cap, append и range
Содержание курса
append с обязательным присваиванием и for range по срезу
append — единственный стандартный способ добавить элемент в срез. Он принимает срез и один или несколько новых значений, а возвращает обновлённый срез:
s := []int{1, 2, 3}
s = append(s, 4)
fmt.Println(s) // [1 2 3 4]
Обычная форма в этом уроке — s = append(s, v). Главное правило: используйте возвращённый срез. Его длина увеличена на число добавленных элементов, а базовый массив мог сохраниться или смениться — это зависит от текущей ёмкости и остаётся деталью реализации.
Результат append можно также присвоить другой переменной, вернуть из функции или сразу передать следующему вызову. Что недопустимо — полностью игнорировать возвращённое значение:
append(s, 4) // ошибка компиляции: append(s, 4) evaluated but not used
Программа не соберётся. Go требует, чтобы возвращённый срез был использован.
append отлично работает с nil-срезом — вы видели его в предыдущей секции:
var s []int
s = append(s, 10, 20)
fmt.Println(s) // [10 20]
Для перебора среза используйте цикл for range:
s := []string{"go", "is", "fun"}
for i, v := range s {
fmt.Println(i, v)
}
// 0 go
// 1 is
// 2 fun
i — индекс, v — копия элемента. Это важно. Если написать:
for _, v := range s {
v = "changed" // не меняет s
}
— срез останется нетронутым. v — локальная переменная итерации, изменение которой не отражается на оригинале. Чтобы изменить элемент, нужно присваивание по индексу:
for i := range s {
s[i] = "changed"
}
fmt.Println(s) // [changed changed changed]
Форма for i := range s даёт только индекс — используйте её, когда значение элемента в теле цикла не нужно. Если нужно только значение без индекса, отбросьте индекс через _:
for _, v := range s {
fmt.Println(v)
}
