вторник, 28 апреля 2020 г.

Четыре базовых range цикла (for-each) в Golang

Базовый for-each цикл (срез или массив)

a := []string{"Foo", "Bar"}
for i, s := range a {
    fmt.Println(i, s)
}

Вывод:

0 Foo
1 Bar

  • Выражение range, a вычисляется один раз перед началом цикла.
  • Значения итерации присваиваются соответствующим переменным итерации, i и s, как в операторе присваивания.
  • Вторая итерационная переменная является необязательной.
  • Для нулевого среза (nil slice) число итераций равно 0.

Итерация строк: руны или байты

Для строк цикл диапазона перебирает Unicode кодовые точки.

for i, ch := range "日本語" {
    fmt.Printf("%#U начинается с позиции байта %d\n", ch, i)
}

Вывод:

U+65E5 '日' начинается с позиции байта 0
U+672C '本' начинается с позиции байта 3
U+8A9E '語' начинается с позиции байта 6

  • Индекс является первым байтом кодированной точки в кодировке UTF-8; второе значение типа rune - это значение кодовой точки.
  • Для недопустимой последовательности UTF-8 второе значение будет 0xFFFD, и итерация продвинется на один байт.

Чтобы перебрать отдельные байты, просто используйте нормальный for цикл и индексацию строки:

const s = "日本語"
for i := 0; i < len(s); i++ {
    fmt.Printf("%x ", s[i])
}

Вывод:

e6 97 a5 e6 9c ac e8 aa 9e

Итерация карт: ключи и значения

Порядок итераций над картами не указан и не гарантируется, что он будет одинаковым для каждой итерации.

m := map[string]int{
    "one":   1,
    "two":   2,
    "three": 3,
}
for k, v := range m {
    fmt.Println(k, v)
}

Вывод:

two 2
three 3
one 1

  • Если запись карты, которая еще не была достигнута, будет удалена во время итерации, это значение не будет создано.
  • Если запись карты создается во время итерации, эта запись может создаваться или не создаваться.
  • Для нулевой карты (nil map) число итераций равно 0.

Итерация канала

Для каналов значения итерации являются последовательными значениями, отправляемыми в канале до его закрытия.

ch := make(chan int)
go func() {
    ch <- 1
    ch <- 2
    ch <- 3
    close(ch)
}()
for n := range ch {
    fmt.Println(n)
}

Вывод:

1
2
3

Для нулевого канала (nil channel) range цикл блокируется навсегда.


Читайте также:


Комментариев нет:

Отправить комментарий