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 循环自定义的迭代逻辑。该包定义了 SeqSeq2 类型,以及相关的辅助函数,为集合遍历提供了统一的方式。

包导入

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