Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Go iter 包详解

概述

iter 包是 Go 1.23 引入的新包,提供了用于迭代器的基础类型和函数。迭代器是 Go 1.23 的重大更新之一,允许使用 for range 循环自定义的迭代逻辑。该包定义了 Seq 和 Seq2 类型,以及相关的辅助函数,为集合遍历提供了统一的方式。

包导入

import "iter"

基本使用

1. 简单的迭代器

package main

import (
    "fmt"
    "iter"
)

func main() {
    // 创建一个简单的序列
    for v := range iter.Seq[int](func(yield func(int) bool) {
        for i := 0; i < 5; i++ {
            if !yield(i) {
                return
            }
        }
    }) {
        fmt.Println(v)
    }
    // 输出:0 1 2 3 4
}

2. 使用 Seq2 迭代键值对

package main

import (
    "fmt"
    "iter"
)

func main() {
    // 创建键值对序列
    for k, v := range iter.Seq2[int, string](func(yield func(int, string) bool) {
        for i := 0; i < 3; i++ {
            if !yield(i, fmt.Sprintf("item%d", i)) {
                return
            }
        }
    }) {
        fmt.Printf("%d: %s\n", k, v)
    }
    // 输出:
    // 0: item0
    // 1: item1
    // 2: item2
}

3. 自定义迭代器函数

package main

import (
    "fmt"
    "iter"
)

// 创建斐波那契数列迭代器
func Fibonacci(n int) iter.Seq[int] {
    return func(yield func(int) bool) {
        a, b := 0, 1
        for i := 0; i < n; i++ {
            if !yield(a) {
                return
            }
            a, b = b, a+b
        }
    }
}

func main() {
    for v := range Fibonacci(10) {
        fmt.Print(v, " ")
    }
    // 输出:0 1 1 2 3 5 8 13 21 34
}

一、核心类型

Seq

定义:

type Seq[V any] func(yield func(V) bool) bool

说明:

  • 功能:单值迭代器类型
  • 类型参数:V - 迭代值的类型
  • 参数:yield - 用于产生值的函数,返回 false 表示停止迭代
  • 返回值:bool - 表示迭代是否完成
  • 用途:用于 for range 循环的单值迭代

示例:

package main

import (
    "fmt"
    "iter"
)

// 示例 1:创建数字序列
func Range(start, end int) iter.Seq[int] {
    return func(yield func(int) bool) {
        for i := start; i < end; i++ {
            if !yield(i) {
                return
            }
        }
    }
}

func main() {
    // 使用迭代器
    for n := range Range(1, 6) {
        fmt.Println(n)
    }
    // 输出:1 2 3 4 5
    
    // 示例 2:提前退出
    for n := range Range(1, 100) {
        if n > 3 {
            break // 自动停止迭代
        }
        fmt.Println(n)
    }
    // 输出:1 2 3
}

Seq2

定义:

type Seq2[K, V any] func(yield func(K, V) bool) bool

说明:

  • 功能:双值迭代器类型(键值对)
  • 类型参数:
    • K - 键的类型
    • V - 值的类型
  • 参数:yield - 用于产生键值对的函数
  • 返回值:bool - 表示迭代是否完成
  • 用途:用于 for range 循环的键值对迭代

示例:

package main

import (
    "fmt"
    "iter"
)

// 示例 1:创建键值对序列
func Enumerate[T any](slice []T) iter.Seq2[int, T] {
    return func(yield func(int, T) bool) {
        for i, v := range slice {
            if !yield(i, v) {
                return
            }
        }
    }
}

// 示例 2:Map 迭代
func MapItems[K comparable, V any](m map[K]V) iter.Seq2[K, V] {
    return func(yield func(K, V) bool) {
        for k, v := range m {
            if !yield(k, v) {
                return
            }
        }
    }
}

func main() {
    // 使用枚举迭代器
    slice := []string{"a", "b", "c"}
    for i, v := range Enumerate(slice) {
        fmt.Printf("%d: %s\n", i, v)
    }
    // 输出:
    // 0: a
    // 1: b
    // 2: c
    
    // 使用 Map 迭代器
    m := map[string]int{
        "one":   1,
        "two":   2,
        "three": 3,
    }
    for k, v := range MapItems(m) {
        fmt.Printf("%s: %d\n", k, v)
    }
}

二、辅助函数

All

定义:

func All[V any](seq Seq[V]) func() (V, bool)

说明:

  • 功能:将迭代器转换为传统的迭代函数
  • 类型参数:V - 值的类型
  • 参数:seq - 迭代器序列
  • 返回值:func() (V, bool) - 每次调用返回下一个值和是否存在
  • 用途:与不支持 for range 的代码兼容

示例:

package main

import (
    "fmt"
    "iter"
)

func Range(start, end int) iter.Seq[int] {
    return func(yield func(int) bool) {
        for i := start; i < end; i++ {
            if !yield(i) {
                return
            }
        }
    }
}

func main() {
    // 使用 All 转换为传统迭代
    next := iter.All(Range(1, 6))
    
    for {
        v, ok := next()
        if !ok {
            break
        }
        fmt.Println(v)
    }
    // 输出:1 2 3 4 5
    
    // 手动控制迭代
    next2 := iter.All(Range(1, 10))
    fmt.Println(next2()) // 1, true
    fmt.Println(next2()) // 2, true
    fmt.Println(next2()) // 3, true
}

All2

定义:

func All2[K, V any](seq Seq2[K, V]) func() (K, V, bool)

说明:

  • 功能:将双值迭代器转换为传统的迭代函数
  • 类型参数:
    • K - 键的类型
    • V - 值的类型
  • 参数:seq - 双值迭代器序列
  • 返回值:func() (K, V, bool) - 每次调用返回下一个键、值和是否存在
  • 用途:与不支持 for range 的代码兼容

示例:

package main

import (
    "fmt"
    "iter"
)

func Enumerate[T any](slice []T) iter.Seq2[int, T] {
    return func(yield func(int, T) bool) {
        for i, v := range slice {
            if !yield(i, v) {
                return
            }
        }
    }
}

func main() {
    slice := []string{"a", "b", "c"}
    
    // 使用 All2 转换
    next := iter.All2(Enumerate(slice))
    
    for {
        i, v, ok := next()
        if !ok {
            break
        }
        fmt.Printf("%d: %s\n", i, v)
    }
    // 输出:
    // 0: a
    // 1: b
    // 2: c
    
    // 手动控制
    next2 := iter.All2(Enumerate(slice))
    i, v, ok := next2()
    fmt.Printf("%d: %s, ok=%v\n", i, v, ok) // 0: a, ok=true
    
    i, v, ok = next2()
    fmt.Printf("%d: %s, ok=%v\n", i, v, ok) // 1: b, ok=true
}

Pull

定义:

func Pull[V any](seq Seq[V]) func(func() V, func() bool)

说明:

  • 功能:将迭代器转换为 pull 风格的迭代器
  • 类型参数:V - 值的类型
  • 参数:seq - 迭代器序列
  • 返回值:接收两个函数的函数
  • 用途:更灵活地控制迭代过程

示例:

package main

import (
    "fmt"
    "iter"
)

func Range(start, end int) iter.Seq[int] {
    return func(yield func(int) bool) {
        for i := start; i < end; i++ {
            if !yield(i) {
                return
            }
        }
    }
}

func main() {
    // 使用 Pull 创建 pull 风格迭代器
    iter.Pull(Range(1, 6))(
        func() V {
            // 获取值的回调
            return // 实际使用中会返回值
        },
        func() bool {
            // 检查是否还有值的回调
            return true
        },
    )
}

Pull2

定义:

func Pull2[K, V any](seq Seq2[K, V]) func(func() (K, V), func() bool)

说明:

  • 功能:将双值迭代器转换为 pull 风格的迭代器
  • 类型参数:
    • K - 键的类型
    • V - 值的类型
  • 参数:seq - 双值迭代器序列
  • 返回值:接收两个函数的函数
  • 用途:更灵活地控制键值对迭代

三、典型示例

示例 1:链表迭代器

package main

import (
    "fmt"
    "iter"
)

// Node 链表节点
type Node[T any] struct {
    Value T
    Next  *Node[T]
}

// List 链表
type List[T any] struct {
    Head *Node[T]
}

// All 返回迭代器
func (l *List[T]) All() iter.Seq[T] {
    return func(yield func(T) bool) {
        current := l.Head
        for current != nil {
            if !yield(current.Value) {
                return
            }
            current = current.Next
        }
    }
}

// AllWithIndex 返回带索引的迭代器
func (l *List[T]) AllWithIndex() iter.Seq2[int, T] {
    return func(yield func(int, T) bool) {
        current := l.Head
        index := 0
        for current != nil {
            if !yield(index, current.Value) {
                return
            }
            current = current.Next
            index++
        }
    }
}

func main() {
    // 创建链表
    list := &List[int]{}
    list.Head = &Node[int]{Value: 1}
    list.Head.Next = &Node[int]{Value: 2}
    list.Head.Next.Next = &Node[int]{Value: 3}
    
    // 遍历链表
    fmt.Print("链表:")
    for v := range list.All() {
        fmt.Print(v, " ")
    }
    fmt.Println()
    // 输出:链表:1 2 3
    
    // 带索引遍历
    fmt.Println("带索引:")
    for i, v := range list.AllWithIndex() {
        fmt.Printf("[%d]=%d ", i, v)
    }
    fmt.Println()
    // 输出:带索引:[0]=1 [1]=2 [2]=3
}

示例 2:树形结构迭代

package main

import (
    "fmt"
    "iter"
)

// TreeNode 树节点
type TreeNode struct {
    Value    int
    Children []*TreeNode
}

// DFS 深度优先遍历
func (n *TreeNode) DFS() iter.Seq[int] {
    return func(yield func(int) bool) {
        n.dfsRecursive(yield)
    }
}

func (n *TreeNode) dfsRecursive(yield func(int) bool) bool {
    if n == nil {
        return true
    }
    
    if !yield(n.Value) {
        return false
    }
    
    for _, child := range n.Children {
        if !child.dfsRecursive(yield) {
            return false
        }
    }
    
    return true
}

// BFS 广度优先遍历
func (n *TreeNode) BFS() iter.Seq[int] {
    return func(yield func(int) bool) {
        if n == nil {
            return
        }
        
        queue := []*TreeNode{n}
        for len(queue) > 0 {
            node := queue[0]
            queue = queue[1:]
            
            if !yield(node.Value) {
                return
            }
            
            queue = append(queue, node.Children...)
        }
    }
}

func main() {
    // 创建树
    root := &TreeNode{Value: 1}
    node2 := &TreeNode{Value: 2}
    node3 := &TreeNode{Value: 3}
    node4 := &TreeNode{Value: 4}
    node5 := &TreeNode{Value: 5}
    
    root.Children = []*TreeNode{node2, node3}
    node2.Children = []*TreeNode{node4, node5}
    
    // DFS 遍历
    fmt.Print("DFS: ")
    for v := range root.DFS() {
        fmt.Print(v, " ")
    }
    fmt.Println()
    // 输出:DFS: 1 2 4 5 3
    
    // BFS 遍历
    fmt.Print("BFS: ")
    for v := range root.BFS() {
        fmt.Print(v, " ")
    }
    fmt.Println()
    // 输出:BFS: 1 2 3 4 5
}

示例 3:通道迭代器

package main

import (
    "fmt"
    "iter"
)

// FromChannel 从通道创建迭代器
func FromChannel[T any](ch <-chan T) iter.Seq[T] {
    return func(yield func(T) bool) {
        for v := range ch {
            if !yield(v) {
                return
            }
        }
    }
}

// ToChannel 将迭代器转换为通道
func ToChannel[T any](seq iter.Seq[T]) <-chan T {
    ch := make(chan T)
    go func() {
        defer close(ch)
        for v := range seq {
            ch <- v
        }
    }()
    return ch
}

func main() {
    // 创建通道
    ch := make(chan int)
    go func() {
        for i := 0; i < 5; i++ {
            ch <- i
        }
        close(ch)
    }()
    
    // 使用迭代器遍历通道
    fmt.Print("通道迭代:")
    for v := range FromChannel(ch) {
        fmt.Print(v, " ")
    }
    fmt.Println()
    
    // 将迭代器转换为通道
    seq := func(yield func(int) bool) {
        for i := 0; i < 5; i++ {
            if !yield(i) {
                return
            }
        }
    }
    
    ch2 := ToChannel(seq)
    fmt.Print("迭代器转通道:")
    for v := range ch2 {
        fmt.Print(v, " ")
    }
    fmt.Println()
}

示例 4:过滤和转换

package main

import (
    "fmt"
    "iter"
    "strings"
)

// Filter 过滤迭代器
func Filter[T any](seq iter.Seq[T], predicate func(T) bool) iter.Seq[T] {
    return func(yield func(T) bool) {
        for v := range seq {
            if predicate(v) {
                if !yield(v) {
                    return
                }
            }
        }
    }
}

// Map 转换迭代器
func Map[T, U any](seq iter.Seq[T], transform func(T) U) iter.Seq[U] {
    return func(yield func(U) bool) {
        for v := range seq {
            if !yield(transform(v)) {
                return
            }
        }
    }
}

// Take 取前 N 个元素
func Take[T any](seq iter.Seq[T], n int) iter.Seq[T] {
    return func(yield func(T) bool) {
        count := 0
        for v := range seq {
            if count >= n {
                return
            }
            if !yield(v) {
                return
            }
            count++
        }
    }
}

func main() {
    // 创建序列
    numbers := func(yield func(int) bool) {
        for i := 1; i <= 10; i++ {
            if !yield(i) {
                return
            }
        }
    }
    
    // 过滤偶数
    fmt.Print("偶数:")
    for n := range Filter(numbers, func(n int) bool {
        return n%2 == 0
    }) {
        fmt.Print(n, " ")
    }
    fmt.Println()
    // 输出:偶数:2 4 6 8 10
    
    // 转换为平方
    fmt.Print("平方:")
    for n := range Map(numbers, func(n int) int {
        return n * n
    }) {
        fmt.Print(n, " ")
    }
    fmt.Println()
    // 输出:平方:1 4 9 16 25 36 49 64 81 100
    
    // 取前 5 个
    fmt.Print("前 5 个:")
    for n := range Take(numbers, 5) {
        fmt.Print(n, " ")
    }
    fmt.Println()
    // 输出:前 5 个:1 2 3 4 5
    
    // 链式操作
    fmt.Print("前 5 个偶数的平方:")
    for n := range Take(Map(Filter(numbers, func(n int) bool {
        return n%2 == 0
    }), func(n int) int {
        return n * n
    }), 5) {
        fmt.Print(n, " ")
    }
    fmt.Println()
    // 输出:前 5 个偶数的平方:4 16 36 64 100
}

示例 5:字符串处理

package main

import (
    "fmt"
    "iter"
    "strings"
)

// Lines 按行迭代字符串
func Lines(s string) iter.Seq[string] {
    return func(yield func(string) bool) {
        for _, line := range strings.Split(s, "\n") {
            if !yield(line) {
                return
            }
        }
    }
}

// Words 按单词迭代字符串
func Words(s string) iter.Seq[string] {
    return func(yield func(string) bool) {
        for _, word := range strings.Fields(s) {
            if !yield(word) {
                return
            }
        }
    }
}

// Runes 按字符迭代字符串
func Runes(s string) iter.Seq[rune] {
    return func(yield func(rune) bool) {
        for _, r := range s {
            if !yield(r) {
                return
            }
        }
    }
}

func main() {
    text := `Hello World
This is Go
iter package`
    
    // 按行迭代
    fmt.Println("按行:")
    for line := range Lines(text) {
        fmt.Printf("  %s\n", line)
    }
    
    // 按单词迭代
    fmt.Println("\n按单词:")
    for word := range Words(text) {
        fmt.Printf("  %s\n", word)
    }
    
    // 按字符迭代
    fmt.Print("\n按字符:")
    count := 0
    for r := range Runes("Hello") {
        if count >= 5 {
            break
        }
        fmt.Printf("%c ", r)
        count++
    }
    fmt.Println()
}

四、最佳实践

1. 提前退出

// 迭代器会自动处理提前退出
func Find[T any](seq iter.Seq[T], predicate func(T) bool) (T, bool) {
    var zero T
    for v := range seq {
        if predicate(v) {
            return v, true
        }
    }
    return zero, false
}

// 使用
result, found := Find(numbers, func(n int) bool {
    return n > 5
})

2. 惰性求值

// 迭代器是惰性求值的,只在需要时计算
func LargeNumbers() iter.Seq[int] {
    return func(yield func(int) bool) {
        fmt.Println("开始生成")
        for i := 0; ; i++ {
            fmt.Printf("生成 %d\n", i)
            if !yield(i) {
                fmt.Println("提前退出")
                return
            }
        }
    }
}

// 只生成前 3 个
for n := range Take(LargeNumbers(), 3) {
    fmt.Println(n)
}

3. 组合操作

// 链式组合多个操作
func ProcessData(data []int) {
    seq := Slice(data)
    
    // 过滤 -> 转换 -> 限制
    for v := range Take(
        Map(
            Filter(seq, func(n int) bool {
                return n%2 == 0
            }),
            func(n int) int {
                return n * n
            },
        ),
        10,
    ) {
        fmt.Println(v)
    }
}

4. 错误处理

// 在迭代器中处理错误
func SafeReadLines(filename string) iter.Seq[string] {
    return func(yield func(string) bool) {
        file, err := os.Open(filename)
        if err != nil {
            return
        }
        defer file.Close()
        
        scanner := bufio.NewScanner(file)
        for scanner.Scan() {
            if !yield(scanner.Text()) {
                return
            }
        }
    }
}

五、与其他包配合

1. 与切片配合

// Slice 将切片转换为迭代器
func Slice[T any](s []T) iter.Seq[T] {
    return func(yield func(T) bool) {
        for _, v := range s {
            if !yield(v) {
                return
            }
        }
    }
}

// Slice2 将切片转换为键值对迭代器
func Slice2[T any](s []T) iter.Seq2[int, T] {
    return func(yield func(int, T) bool) {
        for i, v := range s {
            if !yield(i, v) {
                return
            }
        }
    }
}

2. 与 Map 配合

// Keys 迭代 Map 的键
func Keys[K comparable, V any](m map[K]V) iter.Seq[K] {
    return func(yield func(K) bool) {
        for k := range m {
            if !yield(k) {
                return
            }
        }
    }
}

// Values 迭代 Map 的值
func Values[K comparable, V any](m map[K]V) iter.Seq[V] {
    return func(yield func(V) bool) {
        for _, v := range m {
            if !yield(v) {
                return
            }
        }
    }
}

3. 与通道配合

// 见示例 3:通道迭代器

六、快速参考

类型总览

类型名定义描述
Seq[V]func(yield func(V) bool) bool单值迭代器
Seq2[K,V]func(yield func(K,V) bool) bool双值迭代器

函数总览

函数名参数返回值描述
Allseq Seq[V]func() (V, bool)转换为单值迭代函数
All2seq Seq2[K,V]func() (K, V, bool)转换为双值迭代函数
Pullseq Seq[V]func(...)转换为 pull 风格
Pull2seq Seq2[K,V]func(...)转换为 pull 风格

常见迭代器模式

模式实现方式
序列生成for 循环 + yield
过滤条件判断 + yield
转换转换函数 + yield
限制计数器 + return
树遍历递归 + yield

性能特点

特性说明
惰性求值只在需要时计算
零拷贝不创建中间切片
自动停止支持 break 提前退出
内存高效O(1) 额外空间

七、注意事项

1. yield 的使用

// 正确:检查 yield 返回值
func Correct() iter.Seq[int] {
    return func(yield func(int) bool) {
        for i := 0; i < 10; i++ {
            if !yield(i) {
                return // ✓ 提前退出
            }
        }
    }
}

// 错误:忽略 yield 返回值
func Incorrect() iter.Seq[int] {
    return func(yield func(int) bool) {
        for i := 0; i < 10; i++ {
            yield(i) // ✗ 不检查返回值
        }
    }
}

2. 闭包变量捕获

// 注意:避免闭包捕获循环变量
func BadExample() iter.Seq[func() int] {
    return func(yield func(func() int) bool) {
        for i := 0; i < 3; i++ {
            // ✗ 错误:所有函数都捕获同一个 i
            if !yield(func() int { return i }) {
                return
            }
        }
    }
}

func GoodExample() iter.Seq[func() int] {
    return func(yield func(func() int) bool) {
        for i := 0; i < 3; i++ {
            // ✓ 正确:创建新变量
            v := i
            if !yield(func() int { return v }) {
                return
            }
        }
    }
}

3. 并发安全

// 迭代器本身不是并发安全的
// 需要在外部同步

func ConcurrentSafe(ch <-chan int) iter.Seq[int] {
    return func(yield func(int) bool) {
        // 使用通道保证并发安全
        for v := range ch {
            if !yield(v) {
                return
            }
        }
    }
}

4. 资源管理

// 确保资源正确释放
func WithResource() iter.Seq[string] {
    return func(yield func(string) bool) {
        file, err := os.Open("data.txt")
        if err != nil {
            return
        }
        defer file.Close() // ✓ 使用 defer 保证释放
        
        scanner := bufio.NewScanner(file)
        for scanner.Scan() {
            if !yield(scanner.Text()) {
                return
            }
        }
    }
}

八、完整示例:数据处理管道

package main

import (
    "fmt"
    "iter"
    "strconv"
    "strings"
)

// 数据处理管道示例

// ParseInts 解析字符串为整数
func ParseInts(s string) iter.Seq[int] {
    return func(yield func(int) bool) {
        for _, part := range strings.Fields(s) {
            if n, err := strconv.Atoi(part); err == nil {
                if !yield(n) {
                    return
                }
            }
        }
    }
}

// Filter 过滤
func Filter(seq iter.Seq[int], predicate func(int) bool) iter.Seq[int] {
    return func(yield func(int) bool) {
        for v := range seq {
            if predicate(v) {
                if !yield(v) {
                    return
                }
            }
        }
    }
}

// Map 转换
func Map(seq iter.Seq[int], transform func(int) int) iter.Seq[int] {
    return func(yield func(int) bool) {
        for v := range seq {
            if !yield(transform(v)) {
                return
            }
        }
    }
}

// Sum 求和
func Sum(seq iter.Seq[int]) int {
    sum := 0
    for v := range seq {
        sum += v
    }
    return sum
}

// Count 计数
func Count(seq iter.Seq[int]) int {
    count := 0
    for range seq {
        count++
    }
    return count
}

func main() {
    data := "1 2 3 4 5 6 7 8 9 10"
    
    // 构建数据处理管道
    // 1. 解析字符串
    // 2. 过滤偶数
    // 3. 计算平方
    // 4. 求和
    
    result := Sum(
        Map(
            Filter(
                ParseInts(data),
                func(n int) bool { return n%2 == 0 },
            ),
            func(n int) int { return n * n },
        ),
    )
    
    fmt.Printf("偶数平方和:%d\n", result)
    // 输出:偶数平方和:220 (4+16+36+64+100)
    
    // 统计偶数个数
    count := Count(
        Filter(
            ParseInts(data),
            func(n int) bool { return n%2 == 0 },
        ),
    )
    
    fmt.Printf("偶数个数:%d\n", count)
    // 输出:偶数个数:5
}

最后更新: 2026-04-04
Go 版本: 1.23+
包文档: https://pkg.go.dev/iter