Ce face iter.Seq
Un iterator în Go este o funcție care primește o altă funcție, numită de obicei yield, și o apelează pentru fiecare valoare. iter.Seq[V] produce valori simple, iter.Seq2[K, V] produce perechi (ca indice–valoare sau cheie–valoare). Din Go 1.23, for v := range seq și for k, v := range seq2 parcurg astfel de funcții direct.
yield returnează false când bucla se oprește mai devreme (break, return). Iteratorul trebuie atunci să se oprească imediat: if !yield(v) { return }. Altfel programul se oprește cu panic.
Valorile sunt produse doar când sunt cerute, deci un iterator poate fi chiar infinit (șirul lui Fibonacci) sau poate citi date treptat. Funcțiile din slices și maps (All, Values, Keys, Collect, Sorted) primesc sau returnează aceste tipuri.
Parametri
| Parametru | Descriere |
|---|---|
yield |
Funcția apelată pentru fiecare valoare; returnează false când parcurgerea trebuie oprită. |
Ce returnează
Sunt tipuri, nu funcții: le folosești ca tip returnat de funcțiile tale care produc valori.
Exemple
Exemplul 1: Un iterator infinit oprit cu break
package main
import (
"fmt"
"iter"
)
func fibonacci() iter.Seq[int] {
return func(yield func(int) bool) {
a, b := 0, 1
for {
if !yield(a) {
return
}
a, b = b, a+b
}
}
}
func main() {
for n := range fibonacci() {
if n > 100 {
break
}
fmt.Print(n, " ")
}
fmt.Println()
}
Rezultat
0 1 1 2 3 5 8 13 21 34 55 89
Exemplul 2: Seq2: rânduri numerotate dintr-un text
package main
import (
"fmt"
"iter"
"strings"
)
func randuri(text string) iter.Seq2[int, string] {
return func(yield func(int, string) bool) {
for i, r := range strings.Split(text, "\n") {
if !yield(i+1, r) {
return
}
}
}
}
func main() {
poezie := "Pe lângă plopii fără soț\nAdesea am trecut"
for nr, rand := range randuri(poezie) {
fmt.Printf("%d: %s\n", nr, rand)
}
}
Rezultat
1: Pe lângă plopii fără soț
2: Adesea am trecut
Exemplul 3: Un iterator propriu folosit cu funcțiile din slices
package main
import (
"fmt"
"iter"
"slices"
)
func multipli(n, cati int) iter.Seq[int] {
return func(yield func(int) bool) {
for i := 1; i <= cati; i++ {
if !yield(n * i) {
return
}
}
}
}
func main() {
fmt.Println(slices.Collect(multipli(7, 5)))
fmt.Println(slices.Sorted(multipli(-3, 4)))
}
Rezultat
[7 14 21 28 35]
[-12 -9 -6 -3]
Greșeli frecvente
- Ignori rezultatul lui
yieldși continui dupăbreak: programul se oprește cupanic: range function continued iteration after function for loop body returned false. - Te aștepți ca un
iter.Seqsă aibălensau indici: nu este un slice. Strânge valorile cuslices.Collectdacă ai nevoie de ele toate.
Comenzi înrudite
iter.Pull: Transformă un iterator „push” într-unul „pull”: ceri singur fiecare valoare cu next() și închizi cu stop().slices.All: Transformă un slice în iterator: All dă perechi (indice, valoare), Values doar valorile, Backward perechile de la coadă la cap.slices.Collect: Collect strânge valorile unui iterator într-un slice nou; AppendSeq le adaugă la finalul unui slice existent.maps.Keys: Returnează un iterator peste cheile (Keys) sau valorile (Values) unui map, în ordine aleatorie.