Урок 5 из 8 · 20 мин · обновлено
Массивы, срезы и map
Чем массив отличается от среза, как добавлять элементы через append, перебирать их через range и хранить пары «ключ — значение» в map.
Массивы
Массив хранит заданное количество элементов одного типа. Длину указывают в квадратных скобках, и потом её не изменить:
var days [3]string
days[0] = "пн"
fmt.Println(days, len(days))
scores := [3]int{90, 75, 60}
fmt.Println(scores[1])
[пн ] 3
75
Индексы считаются с нуля: scores[1] — второй элемент. Незаполненные элементы получили нулевые значения — пустые строки. len() возвращает длину.
На практике массивы встречаются редко: заранее знать точное количество элементов удаётся нечасто.
Срезы
Срез — список, который может расти. Он объявляется так же, но без числа в скобках:
tasks := []string{"купить хлеб", "позвонить маме"}
tasks = append(tasks, "оплатить интернет")
fmt.Println(tasks, len(tasks))
fmt.Println(tasks[0])
[купить хлеб позвонить маме оплатить интернет] 3
купить хлеб
append добавляет элементы в конец и возвращает новый срез. Поэтому результат всегда сохраняют обратно в переменную: tasks = append(tasks, …).
Из среза можно взять часть — от одного индекса до другого, не включая правую границу:
nums := []int{10, 20, 30, 40, 50}
fmt.Println(nums[1:3])
fmt.Println(nums[:2], nums[3:])
[20 30]
[10 20] [40 50]
Если левую границу не указать, срез берётся с начала, если правую — до конца.
Перебор через range
for с range проходит по срезу и на каждом шаге выдаёт два значения — индекс и элемент:
for i, t := range tasks {
fmt.Println(i+1, t)
}
1 купить хлеб
2 позвонить маме
3 оплатить интернет
Если индекс не нужен, его пропускают через _:
total := 0
for _, n := range nums {
total += n
}
fmt.Println(total)
150
map: ключ и значение
map хранит пары «ключ — значение», как справочник: по названию товара быстро находится цена. В квадратных скобках — тип ключа, после них — тип значения:
prices := map[string]int{
"кофе": 180,
"чай": 120,
}
prices["какао"] = 200
fmt.Println(prices["кофе"], len(prices))
180 3
Если ключа нет, map возвращает нулевое значение — для чисел это 0. Чтобы понять, есть ли ключ на самом деле, берут второе значение:
p, ok := prices["сок"]
fmt.Println(p, ok)
if p, ok := prices["чай"]; ok {
fmt.Println("Чай стоит", p)
}
0 false
Чай стоит 120
Во втором примере переменные объявлены прямо в if через точку с запятой: они видны только внутри этого условия.
Ещё несколько правил:
delete(prices, "какао")удаляет ключ;- пустую map создают через
make(map[string]int); - порядок перебора map через
rangeкаждый раз может быть разным. Если нужен порядок, ключи сортируют отдельно.
Попробуйте сами. Есть срез заказов: []string{"чай", "кофе", "чай", "сок", "чай", "кофе"}. Посчитайте, сколько раз заказали каждый напиток, и выведите количество для чая, кофе, сока и какао.
Решение
package main
import "fmt"
func main() {
words := []string{"чай", "кофе", "чай", "сок", "чай", "кофе"}
counts := make(map[string]int)
for _, w := range words {
counts[w]++
}
fmt.Println(counts["чай"], counts["кофе"], counts["сок"], counts["какао"])
}
3 2 1 0
Отсутствующий ключ возвращает 0, поэтому counts[w]++ работает сразу, без проверки: первый заказ превращает 0 в 1. Какао не заказывали — для него тоже 0.
Мини-тест: проверьте себя
Закрепите урок: несколько вопросов, разбор ответов — в конце.
-
Чем срез []string отличается от массива [3]string?
Длина массива — часть его типа и не меняется. Срез растёт через append, поэтому в обычном коде используют именно срезы.
-
Почему пишут tasks = append(tasks, "чай"), а не просто append(tasks, "чай")?
append не меняет переменную сама: она возвращает срез с добавленным элементом. Если результат не сохранить, элемент потеряется, а компилятор подскажет об ошибке.
-
nums := []int{10, 20, 30, 40, 50}. Что вернёт nums[1:3]?
Срез берёт элементы с индекса 1 до индекса 3, не включая его. Индексы считаются с нуля: это 20 и 30.
-
В map prices нет ключа "сок". Что вернёт prices["сок"] для map[string]int?
Для отсутствующего ключа map возвращает нулевое значение своего типа. Чтобы отличить «нет ключа» от «значение 0», пишут p, ok := prices["сок"].