Версия: Go 1.23+
Что выведет код?
package main
import "fmt"
func numbers(yield func(int) bool) {
defer fmt.Println("iterator: defer")
for i := 0; i < 5; i++ {
if !yield(i) {
fmt.Println("iterator: stopped")
return
}
fmt.Println("iterator: after yield", i)
}
}
func main() {
for n := range numbers {
fmt.Println("main:", n)
if n == 2 {
break
}
}
fmt.Println("main: done")
}
Многие ждут, что после
break итератор просто мгновенно исчезнет.Но в Go 1.23 появился
range по функции.Под капотом
yield возвращает false, если внешний цикл остановился через break.Ответ:
```txt id="5glpxa"
main: 0
iterator: after yield 0
main: 1
iterator: after yield 1
main: 2
iterator: stopped
iterator: defer
main: done
```
Подвох в том, что `break` происходит во внешнем цикле, но функция-итератор получает сигнал остановки через `yield`.
Если не проверить `!yield(i)`, можно продолжить работу после того, как потребитель уже вышел из цикла.