|
Od verze 1.23 přidalo Go podporu pro
iterátory,
díky kterým můžeme pomocí |
|
![]()
package main
|
|
import (
"fmt"
"iter"
"slices"
"strings"
)
|
|
|
Podívejme se znovu na typ |
type List[T any] struct {
head, tail *element[T]
}
|
type element[T any] struct {
next *element[T]
val T
}
|
|
func (lst *List[T]) Push(v T) {
if lst.tail == nil {
lst.head = &element[T]{val: v}
lst.tail = lst.head
} else {
lst.tail.next = &element[T]{val: v}
lst.tail = lst.tail.next
}
}
|
|
|
All vrací iterátor, což je v Go funkce se speciální signaturou. |
func (lst *List[T]) All() iter.Seq[T] {
return func(yield func(T) bool) {
|
|
Funkce iterátoru přebírá jako parametr jinou
funkci, podle konvence nazvanou |
for e := lst.head; e != nil; e = e.next {
if !yield(e.val) {
return
}
}
}
}
|
|
Iterace nevyžaduje podkladovou datovou strukturu
a nemusí být dokonce ani konečná! Tady je funkce
vracející iterátor přes Fibonacciho čísla: běží tak
dlouho, dokud |
func genFib() 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() {
lst := List[int]{}
lst.Push(10)
lst.Push(13)
lst.Push(23)
|
|
|
Protože |
for e := range lst.All() {
fmt.Println(e)
}
|
|
Balíčky jako slices mají
řadu užitečných funkcí pro práci s iterátory.
Například |
all := slices.Collect(lst.All())
fmt.Println("vše:", all)
|
|
Balíčky standardní knihovny teď také nabízejí
pomocné funkce s iterátory. Například
|
for part := range strings.SplitSeq("go-by-example", "-") {
fmt.Printf("část: %s\n", part)
}
|
for n := range genFib() {
|
|
|
Jakmile cyklus narazí na |
if n >= 10 {
break
}
fmt.Println(n)
}
}
|
$ go run range-over-iterators.go
10
13
23
vše: [10 13 23]
část: go
část: by
část: example
0
1
1
2
3
5
8
|
Další příklad: Chyby (errors).