Перейти к основному содержимому
Модуль 2 · Урок 3 из 58/50 в курсе~10 min
Уроки модуля (3/5)

для...диапазона

for ... range — это идиоматический способ перебора коллекций: срезы, массивы, карты, строки и каналы. Синтаксис немного изменится в зависимости от коллекции, но базовый узор всегда один и тот же: for key, value := range coll { ... }.

Диапазон по срезам и массивам

Возвращает индекс и копию значения:

Go
nums := []int{10, 20, 30}
for i, v := range nums {
    fmt.Println(i, v)
}
// 0 10
// 1 20
// 2 30

Часто достаточно одного из двух:

Go
// solo indice
for i := range nums { _ = i }

// solo valore (ignora indice con _)
for _, v := range nums { _ = v }

Диапазон на карте

Возвращает ключ и значение:

Go
prices := map[string]int{"pane": 2, "latte": 3, "vino": 8}
for k, v := range prices {
    fmt.Println(k, v)
}

Диапазон в строке: руны, а не байты

for i, r := range s выполняет итерацию по каждой кодовой точке Юникода (руне), а не по байт. Индекс i — это байтовое смещение начала руны.

Go
for i, r := range "èé" {
    fmt.Printf("%d %c (%U)\n", i, r, r)
}
// 0 è (U+00E8)
// 2 é (U+00E9)

Для побайтовой итерации используйте классическую индексацию:

Go
s := "ciao"
for i := 0; i < len(s); i++ {
    fmt.Println(s[i])  // byte (uint8)
}

Диапазон на канале

Выполняется до тех пор, пока канал не будет закрыт:

Go
ch := make(chan int)
go func() {
    for i := 0; i < 3; i++ { ch <- i }
    close(ch)
}()
for v := range ch {
    fmt.Println(v)
}

Мы углубимся в модуль Concurrency.

Попробуйте это

Упражнение#go.m2.l3.e1
Попыток: 0Загрузка…

Выведите индекс и значение каждого элемента чисел, используя for-range.

Загрузка редактора…

Решение доступно после 3 попыток

Упражнение#go.m2.l3.e2
Попыток: 0Загрузка…

Суммируйте все значения чисел, игнорируя индекс.

Загрузка редактора…
Показать подсказку

Используйте `_`, чтобы отбросить индекс.

Решение доступно после 3 попыток

Quiz#go.m2.l3.e3
Готово

Что представляет первая переменная в `for k, v := range m`, когда m является картой?

Go
m := map[string]int{"a": 1, "b": 2}
for k, v := range m { fmt.Println(k, v) }
Варианты ответа

Резюме

  • for k, v := range coll с четкой областью действия: удалите с помощью _ то, что вы не используете.
  • Срез/массив: индекс + КОПИЯ значения. Чтобы мутировать, index.
  • Карта: ключ + значение, порядок случайный при каждом запуске.
  • Строка: диапазон повторяется для каждой руны (кодовой точки), а не для каждого байта.
  • Канал: выполняется итерация, пока канал открыт; закрыт с помощью close().