У Go for range повторює блок коду для кожного значення з виразу range.
Вираз range визначає, чи кожна ітерація даватиме одне значення чи два.
range
range по слайсу дає індекс і значення кожного елемента по порядку:
vals := []int{10, 20, 30}
for i, v := range vals {
fmt.Println(i, v)
}
// 0 10
// 1 20
// 2 30
range по мапі дає кожен ключ і значення, але порядок ітерації не гарантований.
Go навмисно рандомізує порядок ітерації мапи, тож та сама програма може щоразу видавати різний вивід.
hash := map[int]int{9: 10, 99: 20, 999: 30}
for k, v := range hash {
fmt.Println(k, v)
}
// 99 20
// 999 30
// 9 10
range по рядку тексту (англ. string) дає байтовий індекс і кожну руну (кодову точку Unicode).
У наведеному нижче прикладі 子 займає три байти, тож 猫 починається з байтового індексу 3, а не 1.
for i, r := range "子猫" {
fmt.Println(i, r, string(r))
}
// 0 23376 子
// 3 29483 猫
Якщо потрібні саме індекси рун, перетворімо рядок тексту на слайс рун:
for i, r := range []rune("子猫") {
fmt.Println(i, r, string(r))
}
// 0 23376 子
// 1 29483 猫
range може перебирати ціле число безпосередньо, даючи значення від 0 до цього числа, не включаючи його.
Нуль і відʼємні значення допустимі, але не дають жодної ітерації.
for n := range 3 {
fmt.Println(n)
}
// 0
// 1
// 2
range приймає ітератор типу iter.Seq[V] або iter.Seq2[K, V].
Ітератор - це функція, яка видає послідовність значень по одному за раз.
Далі range може перебрати ці значення.
text := "The quick brown fox"
for word := range strings.FieldsSeq(text) {
fmt.Println(word)
}
// The
// quick
// brown
// fox
names := []string{"Alice", "Bob", "Vera"}
for i, v := range slices.All(names) {
fmt.Println(i, ":", v)
}
// 0 : Alice
// 1 : Bob
// 2 : Vera
І нарешті, range може приймати значення, надіслані через канал, доки цей канал деінде не закриють.
Канали докладніше розглядаються далі в силабусі track.
Go не скомпілює код, якщо змінна оголошена, але ніде не використовується.
vals := []int{10, 20, 30}
for i, v := range vals {
fmt.Println(v)
}
// Go build failed: declared and not used: i
Якщо потрібне лише значення, присвоймо індекс або ключ _, щоб його проігнорувати.
vals := []int{10, 20, 30}
for _, v := range vals {
fmt.Println(v)
}
// 10
// 20
// 30
Якщо потрібен лише індекс, пропустімо його повністю:
vals := []int{10, 20, 30}
for i := range vals {
fmt.Println(i)
}
// 0
// 1
// 2
Якщо не потрібні ні індекс, ні значення, можна пропустити обидва:
vals := []int{10, 20, 30}
count := 0
for range vals {
count++
}
// count == 3