Go 1.24迭代器进阶:range over func深度实战 2026

编程语言

Go 1.24迭代器进阶:range over func深度实战

Go 1.22引入了range over int,Go 1.23引入了range over func——Go终于有了"一等公民"的迭代器。但很多Gopher还停留在for i, v := range slice的阶段,对range over func的理解仅限于标准库的slicesmaps包。

到了Go 1.24,迭代器生态已经成熟:泛型迭代器、迭代器组合、懒求值管道……这些模式可以让你的Go代码更优雅、更高效、更Go-idiomatic。本文从5个核心模式出发,带你彻底掌握Go迭代器。

核心概念速览

概念 说明 签名
迭代器函数(Iterator Function) 可被range遍历的函数类型 func(yield func(V) bool)
带索引迭代器 同时返回索引和值 func(yield func(int, V) bool)
Pull迭代器 手动拉取下一个值 func() (V, bool)
Push迭代器 推送值给yield回调 func(yield func(V) bool)
迭代器组合 多个迭代器串联/并联 func(...Iter) Iter
懒求值 延迟到实际消费时才计算 迭代器天然懒求值

Go迭代器的5大痛点

  1. 自定义集合遍历繁琐:树、图、链表等结构需要手写遍历回调,代码丑陋
  2. 管道式数据处理缺失:无法像Python生成器那样链式filter/map
  3. 泛型迭代器类型复杂func(yield func(V) bool)的签名让初学者头疼
  4. 迭代器与goroutine交互:并发迭代器的正确使用姿势不清晰
  5. Pull vs Push选择困难:两种迭代器模式何时用哪种不明确

模式一:range over func基础

Go 1.23引入的三种迭代器函数签名,是理解一切的基础。

// go-iterator-basics/main.go
// 运行环境: Go 1.24+ / 无额外依赖
package main

import (
	"fmt"
	"iter"
)

// ============================================================
// 1. 基本迭代器:func(yield func(V) bool)
// ============================================================

// Range 生成整数序列迭代器
func Range(n int) iter.Seq[int] {
	return func(yield func(int) bool) {
		for i := range n {
			if !yield(i) {
				return
			}
		}
	}
}

// RangeWithStep 生成带步长的整数序列
func RangeWithStep(start, end, step int) iter.Seq[int] {
	return func(yield func(int) bool) {
		for i := start; i < end; i += step {
			if !yield(i) {
				return
			}
		}
	}
}

// ============================================================
// 2. 带索引迭代器:func(yield func(K, V) bool)
// ============================================================

// Enumerate 为任意切片添加索引
func Enumerate[T any](items []T) iter.Seq2[int, T] {
	return func(yield func(int, T) bool) {
		for i, item := range items {
			if !yield(i, item) {
				return
			}
		}
	}
}

// ============================================================
// 3. 提前退出:yield返回false时停止迭代
// ============================================================

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

// ============================================================
// 4. Pull迭代器:手动拉取
// ============================================================

// ToPull 将Push迭代器转换为Pull迭代器
func ToPull[T any](seq iter.Seq[T]) func() (T, bool) {
	next, stop := iter.Pull(seq)
	return func() (T, bool) {
		v, ok := next()
		return v, ok
	}
}

// ============================================================
// 使用示例
// ============================================================

func main() {
	fmt.Println("=== 基本迭代器 ===")
	for i := range Range(5) {
		fmt.Print(i, " ") // 0 1 2 3 4
	}
	fmt.Println()

	fmt.Println("=== 带步长 ===")
	for i := range RangeWithStep(0, 20, 5) {
		fmt.Print(i, " ") // 0 5 10 15
	}
	fmt.Println()

	fmt.Println("=== 带索引 ===")
	fruits := []string{"苹果", "香蕉", "橘子"}
	for i, fruit := range Enumerate(fruits) {
		fmt.Printf("%d: %s  ", i, fruit)
	}
	fmt.Println()

	fmt.Println("=== 提前退出 ===")
	for v := range Take(3, Range(100)) {
		fmt.Print(v, " ") // 0 1 2
	}
	fmt.Println()

	fmt.Println("=== Pull迭代器 ===")
	pull := ToPull(Range(3))
	for {
		v, ok := pull()
		if !ok {
			break
		}
		fmt.Print(v, " ") // 0 1 2
	}
	fmt.Println()
}

模式二:泛型迭代器

泛型让迭代器成为真正的"一等公民"——一个Filter函数可以过滤任何类型的序列。

// go-generic-iterator/main.go
// 运行环境: Go 1.24+ / 无额外依赖
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 any, R any](seq iter.Seq[T], transform func(T) R) iter.Seq[R] {
	return func(yield func(R) bool) {
		for v := range seq {
			if !yield(transform(v)) {
				return
			}
		}
	}
}

// FlatMap 对每个元素变换后展平
func FlatMap[T any, R any](seq iter.Seq[T], transform func(T) iter.Seq[R]) iter.Seq[R] {
	return func(yield func(R) bool) {
		for v := range seq {
			for r := range transform(v) {
				if !yield(r) {
					return
				}
			}
		}
	}
}

// Reduce 将序列归约为单个值
func Reduce[T any, R any](seq iter.Seq[T], initial R, accumulator func(R, T) R) R {
	result := initial
	for v := range seq {
		result = accumulator(result, v)
	}
	return result
}

// Zip 将两个序列合并为元组序列
func Zip[T any, U any](seq1 iter.Seq[T], seq2 iter.Seq[U]) iter.Seq2[T, U] {
	return func(yield func(T, U) bool) {
		next1, stop1 := iter.Pull(seq1)
		next2, stop2 := iter.Pull(seq2)
		defer stop1()
		defer stop2()

		for {
			v1, ok1 := next1()
			v2, ok2 := next2()
			if !ok1 || !ok2 {
				return
			}
			if !yield(v1, v2) {
				return
			}
		}
	}
}

// Chunk 将序列分块
func Chunk[T any](size int, seq iter.Seq[T]) iter.Seq[[]T] {
	return func(yield func([]T) bool) {
		chunk := make([]T, 0, size)
		for v := range seq {
			chunk = append(chunk, v)
			if len(chunk) == size {
				if !yield(chunk) {
					return
				}
				chunk = make([]T, 0, size)
			}
		}
		if len(chunk) > 0 {
			yield(chunk)
		}
	}
}

// Distinct 去重
func Distinct[T comparable](seq iter.Seq[T]) iter.Seq[T] {
	return func(yield func(T) bool) {
		seen := make(map[T]bool)
		for v := range seq {
			if !seen[v] {
				seen[v] = true
				if !yield(v) {
					return
				}
			}
		}
	}
}

// ============================================================
// 使用示例
// ============================================================

func main() {
	// 从切片创建迭代器
	numbers := slicesToIter([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})

	// 链式操作:过滤偶数 → 平方 → 取前3个
	evens := Filter(numbers, func(n int) bool { return n%2 == 0 })
	squares := Map(evens, func(n int) int { return n * n })
	first3 := Take(3, squares)

	fmt.Print("链式操作: ")
	for v := range first3 {
		fmt.Print(v, " ") // 4 16 36
	}
	fmt.Println()

	// Reduce求和
	sum := Reduce(slicesToIter([]int{1, 2, 3, 4, 5}), 0,
		func(acc, n int) int { return acc + n })
	fmt.Println("求和:", sum) // 15

	// Chunk分块
	fmt.Print("分块: ")
	for chunk := range Chunk(3, slicesToIter([]int{1, 2, 3, 4, 5, 6, 7})) {
		fmt.Print(chunk, " ") // [1 2 3] [4 5 6] [7]
	}
	fmt.Println()

	// Distinct去重
	fmt.Print("去重: ")
	for v := range Distinct(slicesToIter([]string{"go", "rust", "go", "python", "rust"})) {
		fmt.Print(v, " ") // go rust python
	}
	fmt.Println()

	// FlatMap展平
	sentences := slicesToIter([]string{"hello world", "go is great"})
	words := FlatMap(sentences, func(s string) iter.Seq[string] {
		return slicesToIter(strings.Split(s, " "))
	})
	fmt.Print("展平: ")
	for w := range words {
		fmt.Print(w, " ") // hello world go is great
	}
	fmt.Println()
}

// 辅助函数:切片转迭代器
func slicesToIter[T any](s []T) iter.Seq[T] {
	return func(yield func(T) bool) {
		for _, v := range s {
			if !yield(v) {
				return
			}
		}
	}
}

模式三:树/图遍历迭代器

迭代器最强大的应用场景——将递归遍历变成可组合的管道。

// go-tree-iterator/main.go
// 运行环境: Go 1.24+ / 无额外依赖
package main

import (
	"fmt"
	"iter"
)

// ============================================================
// 二叉树定义与迭代器
// ============================================================

type TreeNode[T any] struct {
	Value T
	Left  *TreeNode[T]
	Right *TreeNode[T]
}

// InOrder 中序遍历迭代器(左-根-右)
func (n *TreeNode[T]) InOrder() iter.Seq[T] {
	return func(yield func(T) bool) {
		n.inOrderHelper(yield)
	}
}

func (n *TreeNode[T]) inOrderHelper(yield func(T) bool) bool {
	if n == nil {
		return true
	}
	if !n.Left.inOrderHelper(yield) {
		return false
	}
	if !yield(n.Value) {
		return false
	}
	if !n.Right.inOrderHelper(yield) {
		return false
	}
	return true
}

// PreOrder 前序遍历迭代器(根-左-右)
func (n *TreeNode[T]) PreOrder() iter.Seq[T] {
	return func(yield func(T) bool) {
		n.preOrderHelper(yield)
	}
}

func (n *TreeNode[T]) preOrderHelper(yield func(T) bool) bool {
	if n == nil {
		return true
	}
	if !yield(n.Value) {
		return false
	}
	if !n.Left.preOrderHelper(yield) {
		return false
	}
	if !n.Right.preOrderHelper(yield) {
		return false
	}
	return true
}

// PostOrder 后序遍历迭代器(左-右-根)
func (n *TreeNode[T]) PostOrder() iter.Seq[T] {
	return func(yield func(T) bool) {
		n.postOrderHelper(yield)
	}
}

func (n *TreeNode[T]) postOrderHelper(yield func(T) bool) bool {
	if n == nil {
		return true
	}
	if !n.Left.postOrderHelper(yield) {
		return false
	}
	if !n.Right.postOrderHelper(yield) {
		return false
	}
	if !yield(n.Value) {
		return false
	}
	return true
}

// LevelOrder 层序遍历迭代器(BFS)
func (n *TreeNode[T]) LevelOrder() iter.Seq[T] {
	return func(yield func(T) bool) {
		if n == nil {
			return
		}
		queue := []*TreeNode[T]{n}
		for len(queue) > 0 {
			current := queue[0]
			queue = queue[1:]
			if !yield(current.Value) {
				return
			}
			if current.Left != nil {
				queue = append(queue, current.Left)
			}
			if current.Right != nil {
				queue = append(queue, current.Right)
			}
		}
	}
}

// ============================================================
// 图定义与迭代器
// ============================================================

type Graph[T comparable] struct {
	adjList map[T][]T
}

func NewGraph[T comparable]() *Graph[T] {
	return &Graph[T]{
		adjList: make(map[T][]T),
	}
}

func (g *Graph[T]) AddEdge(from, to T) {
	g.adjList[from] = append(g.adjList[from], to)
}

// DFS 深度优先遍历迭代器
func (g *Graph[T]) DFS(start T) iter.Seq[T] {
	return func(yield func(T) bool) {
		visited := make(map[T]bool)
		g.dfsHelper(start, visited, yield)
	}
}

func (g *Graph[T]) dfsHelper(node T, visited map[T]bool, yield func(T) bool) bool {
	if visited[node] {
		return true
	}
	visited[node] = true
	if !yield(node) {
		return false
	}
	for _, neighbor := range g.adjList[node] {
		if !g.dfsHelper(neighbor, visited, yield) {
			return false
		}
	}
	return true
}

// BFS 广度优先遍历迭代器
func (g *Graph[T]) BFS(start T) iter.Seq[T] {
	return func(yield func(T) bool) {
		visited := make(map[T]bool)
		queue := []T{start}
		visited[start] = true

		for len(queue) > 0 {
			node := queue[0]
			queue = queue[1:]
			if !yield(node) {
				return
			}
			for _, neighbor := range g.adjList[node] {
				if !visited[neighbor] {
					visited[neighbor] = true
					queue = append(queue, neighbor)
				}
			}
		}
	}
}

// ============================================================
// 使用示例
// ============================================================

func main() {
	// 构建二叉树:
	//       4
	//      / \
	//     2   6
	//    / \ / \
	//   1  3 5  7
	root := &TreeNode[int]{
		Value: 4,
		Left:  &TreeNode[int]{Value: 2, Left: &TreeNode[int]{Value: 1}, Right: &TreeNode[int]{Value: 3}},
		Right: &TreeNode[int]{Value: 6, Left: &TreeNode[int]{Value: 5}, Right: &TreeNode[int]{Value: 7}},
	}

	fmt.Print("中序: ")
	for v := range root.InOrder() {
		fmt.Print(v, " ") // 1 2 3 4 5 6 7
	}
	fmt.Println()

	fmt.Print("前序: ")
	for v := range root.PreOrder() {
		fmt.Print(v, " ") // 4 2 1 3 6 5 7
	}
	fmt.Println()

	fmt.Print("后序: ")
	for v := range root.PostOrder() {
		fmt.Print(v, " ") // 1 3 2 5 7 6 4
	}
	fmt.Println()

	fmt.Print("层序: ")
	for v := range root.LevelOrder() {
		fmt.Print(v, " ") // 4 2 6 1 3 5 7
	}
	fmt.Println()

	// 图遍历
	g := NewGraph[string]()
	g.AddEdge("A", "B")
	g.AddEdge("A", "C")
	g.AddEdge("B", "D")
	g.AddEdge("C", "D")
	g.AddEdge("D", "E")

	fmt.Print("DFS: ")
	for v := range g.DFS("A") {
		fmt.Print(v, " ") // A B D E C
	}
	fmt.Println()

	fmt.Print("BFS: ")
	for v := range g.BFS("A") {
		fmt.Print(v, " ") // A B C D E
	}
	fmt.Println()
}

模式四:迭代器组合与管道

迭代器最优雅的用法——像Unix管道一样组合数据处理流程。

// go-iterator-pipeline/main.go
// 运行环境: Go 1.24+ / 无额外依赖
package main

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

// ============================================================
// 迭代器组合器
// ============================================================

// Concat 连接多个迭代器
func Concat[T any](seqs ...iter.Seq[T]) iter.Seq[T] {
	return func(yield func(T) bool) {
		for _, seq := range seqs {
			for v := range seq {
				if !yield(v) {
					return
				}
			}
		}
	}
}

// Interleave 交替输出多个迭代器的元素
func Interleave[T any](seqs ...iter.Seq[T]) iter.Seq[T] {
	return func(yield func(T) bool) {
		pulls := make([]func() (T, bool), len(seqs))
		stops := make([]func(), len(seqs))
		for i, seq := range seqs {
			pulls[i], stops[i] = iter.Pull(seq)
		}
		defer func() {
			for _, stop := range stops {
				stop()
			}
		}()

		active := len(seqs)
		for active > 0 {
			for i, pull := range pulls {
				v, ok := pull()
				if !ok {
					pulls[i] = nil
					active--
					continue
				}
				if !yield(v) {
					return
				}
			}
		}
	}
}

// Cycle 无限循环迭代器
func Cycle[T any](seq iter.Seq[T]) iter.Seq[T] {
	return func(yield func(T) bool) {
		for {
			for v := range seq {
				if !yield(v) {
					return
				}
			}
		}
	}
}

// TakeWhile 在条件为true时取值
func TakeWhile[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) {
				return
			}
			if !yield(v) {
				return
			}
		}
	}
}

// DropWhile 跳过条件为true的元素
func DropWhile[T any](seq iter.Seq[T], predicate func(T) bool) iter.Seq[T] {
	return func(yield func(T) bool) {
		dropping := true
		for v := range seq {
			if dropping && predicate(v) {
				continue
			}
			dropping = false
			if !yield(v) {
				return
			}
		}
	}
}

// Tee 将一个迭代器复制为两个
func Tee[T any](seq iter.Seq[T]) (iter.Seq[T], iter.Seq[T]) {
	// 收集所有值(注意:会消耗内存)
	var values []T
	for v := range seq {
		values = append(values, v)
	}
	return slicesToIter(values), slicesToIter(values)
}

// ============================================================
// 实战:日志处理管道
// ============================================================

type LogEntry struct {
	Timestamp string
	Level     string
	Message   string
}

func ParseLogs(rawLines iter.Seq[string]) iter.Seq[LogEntry] {
	return Map(rawLines, func(line string) LogEntry {
		parts := strings.SplitN(line, " ", 3)
		if len(parts) < 3 {
			return LogEntry{Message: line}
		}
		return LogEntry{
			Timestamp: parts[0],
			Level:     parts[1],
			Message:   parts[2],
		}
	})
}

func FilterByLevel(level string, logs iter.Seq[LogEntry]) iter.Seq[LogEntry] {
	return Filter(logs, func(l LogEntry) bool {
		return l.Level == level
	})
}

func ExtractMessages(logs iter.Seq[LogEntry]) iter.Seq[string] {
	return Map(logs, func(l LogEntry) string {
		return l.Message
	})
}

// ============================================================
// 使用示例
// ============================================================

func main() {
	// Concat连接
	fmt.Print("连接: ")
	for v := range Concat(
		slicesToIter([]int{1, 2, 3}),
		slicesToIter([]int{4, 5, 6}),
	) {
		fmt.Print(v, " ") // 1 2 3 4 5 6
	}
	fmt.Println()

	// Interleave交替
	fmt.Print("交替: ")
	for v := range Interleave(
		slicesToIter([]string{"A", "B", "C"}),
		slicesToIter([]string{"1", "2", "3"}),
	) {
		fmt.Print(v, " ") // A 1 B 2 C 3
	}
	fmt.Println()

	// TakeWhile
	fmt.Print("TakeWhile: ")
	for v := range TakeWhile(
		slicesToIter([]int{1, 2, 3, 10, 4, 5}),
		func(n int) bool { return n < 5 },
	) {
		fmt.Print(v, " ") // 1 2 3
	}
	fmt.Println()

	// DropWhile
	fmt.Print("DropWhile: ")
	for v := range DropWhile(
		slicesToIter([]int{1, 2, 3, 10, 4, 5}),
		func(n int) bool { return n < 5 },
	) {
		fmt.Print(v, " ") // 10 4 5
	}
	fmt.Println()

	// 日志处理管道
	rawLogs := slicesToIter([]string{
		"2026-01-01 ERROR 数据库连接失败",
		"2026-01-01 INFO 服务启动",
		"2026-01-01 ERROR 缓存超时",
		"2026-01-01 WARN 内存使用率高",
	})

	fmt.Println("\n=== 日志管道:只看ERROR消息 ===")
	errorMessages := ExtractMessages(FilterByLevel("ERROR", ParseLogs(rawLogs)))
	for msg := range errorMessages {
		fmt.Println("  ", msg)
	}
}

// ============================================================
// 复用工具函数
// ============================================================

func slicesToIter[T any](s []T) iter.Seq[T] {
	return func(yield func(T) bool) {
		for _, v := range s {
			if !yield(v) {
				return
			}
		}
	}
}

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
				}
			}
		}
	}
}

func Map[T any, R any](seq iter.Seq[T], transform func(T) R) iter.Seq[R] {
	return func(yield func(R) bool) {
		for v := range seq {
			if !yield(transform(v)) {
				return
			}
		}
	}
}

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

模式五:生产级迭代器模式

将迭代器应用于真实的生产场景:数据库分页、文件流处理、并发迭代。

// go-production-iterator/main.go
// 运行环境: Go 1.24+ / 无额外依赖
package main

import (
	"bufio"
	"fmt"
	"iter"
	"os"
	"strings"
)

// ============================================================
// 1. 分页迭代器:模拟数据库分页查询
// ============================================================

type Page[T any] struct {
	Items    []T
	PageNum  int
	HasMore  bool
}

// Paginate 分页迭代器
func Paginate[T any](
	fetchPage func(pageNum int) (Page[T], error),
) iter.Seq2[int, T] {
	return func(yield func(int, T) bool) {
		pageNum := 0
		for {
			page, err := fetchPage(pageNum)
			if err != nil {
				return
			}
			for _, item := range page.Items {
				if !yield(pageNum, item) {
					return
				}
			}
			if !page.HasMore {
				return
			}
			pageNum++
		}
	}
}

// ============================================================
// 2. 文件行迭代器:懒读取大文件
// ============================================================

// Lines 按行读取文件迭代器
func Lines(filePath string) iter.Seq2[int, string] {
	return func(yield func(int, string) bool) {
		file, err := os.Open(filePath)
		if err != nil {
			return
		}
		defer file.Close()

		scanner := bufio.NewScanner(file)
		lineNum := 0
		for scanner.Scan() {
			lineNum++
			if !yield(lineNum, scanner.Text()) {
				return
			}
		}
	}
}

// LinesFromString 从字符串按行读取
func LinesFromString(s string) iter.Seq[string] {
	return func(yield func(string) bool) {
		scanner := bufio.NewScanner(strings.NewReader(s))
		for scanner.Scan() {
			if !yield(scanner.Text()) {
				return
			}
		}
	}
}

// ============================================================
// 3. 带缓冲的迭代器:预取提高性能
// ============================================================

// Buffered 创建带缓冲的迭代器
func Buffered[T any](size int, seq iter.Seq[T]) iter.Seq[T] {
	return func(yield func(T) bool) {
		buffer := make(chan T, size)
		done := make(chan struct{})

		// 生产者:预取数据到缓冲
		go func() {
			defer close(buffer)
			for v := range seq {
				select {
				case buffer <- v:
				case <-done:
					return
				}
			}
		}()

		// 消费者:从缓冲读取
		for v := range buffer {
			if !yield(v) {
				close(done)
				return
			}
		}
	}
}

// ============================================================
// 4. 去重迭代器(有序序列)
// ============================================================

// Deduplicate 对有序序列去重(无需额外内存)
func Deduplicate[T comparable](seq iter.Seq[T]) iter.Seq[T] {
	return func(yield func(T) bool) {
		var prev T
		first := true
		for v := range seq {
			if first || v != prev {
				first = false
				prev = v
				if !yield(v) {
					return
				}
			}
		}
	}
}

// ============================================================
// 5. 带索引的滑动窗口迭代器
// ============================================================

// SlidingWindow 滑动窗口迭代器
func SlidingWindow[T any](size int, seq iter.Seq[T]) iter.Seq[[]T] {
	return func(yield func([]T) bool) {
		window := make([]T, 0, size)
		for v := range seq {
			window = append(window, v)
			if len(window) > size {
				window = window[1:]
			}
			if len(window) == size {
				// 复制窗口避免后续修改影响
				snapshot := make([]T, size)
				copy(snapshot, window)
				if !yield(snapshot) {
					return
				}
			}
		}
	}
}

// ============================================================
// 使用示例
// ============================================================

func main() {
	// 分页迭代器模拟
	fmt.Println("=== 分页迭代器 ===")
	mockFetchPage := func(pageNum int) (Page[string], error) {
		allItems := [][]string{
			{"用户1", "用户2", "用户3"},
			{"用户4", "用户5", "用户6"},
			{"用户7"},
		}
		if pageNum >= len(allItems) {
			return Page[string]{HasMore: false}, nil
		}
		return Page[string]{
			Items:   allItems[pageNum],
			PageNum: pageNum,
			HasMore: pageNum < len(allItems)-1,
		}, nil
	}

	for pageNum, user := range Paginate(mockFetchPage) {
		fmt.Printf("  页%d: %s\n", pageNum, user)
	}

	// 文件行迭代器
	fmt.Println("\n=== 字符串行迭代器 ===")
	content := `第一行数据
第二行数据
第三行数据`
	for line := range LinesFromString(content) {
		fmt.Println("  ", line)
	}

	// 滑动窗口
	fmt.Println("\n=== 滑动窗口 ===")
	for window := range SlidingWindow(3, slicesToIter([]int{1, 2, 3, 4, 5, 6, 7})) {
		fmt.Print(window, " ") // [1 2 3] [2 3 4] [3 4 5] [4 5 6] [5 6 7]
	}
	fmt.Println()

	// 有序去重
	fmt.Print("有序去重: ")
	for v := range Deduplicate(slicesToIter([]int{1, 1, 2, 2, 3, 3, 3, 4})) {
		fmt.Print(v, " ") // 1 2 3 4
	}
	fmt.Println()
}

func slicesToIter[T any](s []T) iter.Seq[T] {
	return func(yield func(T) bool) {
		for _, v := range s {
			if !yield(v) {
				return
			}
		}
	}
}

避坑指南:5个常见陷阱

坑1:迭代器中修改底层集合

// ❌ 错误:遍历时修改切片导致未定义行为
for i, v := range mySlice {
    mySlice = append(mySlice, v) // 危险!
}

// ✅ 正确:迭代器是快照语义,但底层集合可能变化
// 如果需要安全遍历,先复制
copied := make([]int, len(mySlice))
copy(copied, mySlice)
for v := range slicesToIter(copied) {
    // 安全修改原切片
}

坑2:Pull迭代器忘记调用stop

// ❌ 错误:Pull后未调用stop,可能泄漏goroutine
next, _ := iter.Pull(mySeq)  // stop被忽略了!
v, ok := next()

// ✅ 正确:始终defer stop
next, stop := iter.Pull(mySeq)
defer stop()
v, ok := next()

坑3:迭代器重用导致意外行为

// ❌ 错误:迭代器是消耗性的,不能重用
seq := Range(5)
for v := range seq { fmt.Print(v) } // 0 1 2 3 4
for v := range seq { fmt.Print(v) } // 无输出!已消耗

// ✅ 正确:每次创建新迭代器
for v := range Range(5) { fmt.Print(v) }
for v := range Range(5) { fmt.Print(v) }

坑4:递归迭代器栈溢出

// ❌ 错误:深度递归树可能栈溢出
func (n *TreeNode[T]) InOrder() iter.Seq[T] {
    return func(yield func(T) bool) {
        // 深度100万层 → 栈溢出
        for v := range n.Left.InOrder() { yield(v) }
        yield(n.Value)
        for v := range n.Right.InOrder() { yield(v) }
    }
}

// ✅ 正确:深度树使用显式栈(层序遍历方式)
func (n *TreeNode[T]) InOrderSafe() iter.Seq[T] {
    return func(yield func(T) bool) {
        var stack []*TreeNode[T]
        current := n
        for current != nil || len(stack) > 0 {
            for current != nil {
                stack = append(stack, current)
                current = current.Left
            }
            current = stack[len(stack)-1]
            stack = stack[:len(stack)-1]
            if !yield(current.Value) { return }
            current = current.Right
        }
    }
}

坑5:goroutine泄漏

// ❌ 错误:Buffered迭代器中消费者提前退出,goroutine泄漏
for v := range Buffered(10, someSeq) {
    if v > 100 { break } // break后生产者goroutine可能永远阻塞
}

// ✅ 正确:确保done channel能通知生产者退出
// Buffered实现中已使用select+done处理

报错排查表

报错信息 原因 解决方案
cannot range over xxx 类型不是iter.Seq/iter.Seq2 确认函数签名是func(yield func(V) bool)
yield is not used 迭代器函数中未调用yield 确保在循环中调用yield(v)
cannot use seq as iter.Seq 迭代器签名不匹配 检查iter.Seq[T]vsiter.Seq2[K,V]
panic: range over nil 迭代器函数为nil 添加nil检查,返回空迭代器
goroutine leak Pull迭代器未调用stop defer stop()
stack overflow 递归迭代器深度过大 改用显式栈迭代
deadlock 迭代器内部channel阻塞 添加context取消或超时机制
unexpected address yield返回的是副本 Go值语义,需要取地址请用指针*T
iterator consumed twice 迭代器只能消耗一次 每次创建新迭代器或缓存结果
invalid memory address 迭代器中访问已关闭资源 确保资源在迭代完成后才关闭

进阶优化:5个生产级技巧

技巧1:迭代器与context集成

// 带context取消的迭代器
func ContextAware[T any](ctx context.Context, seq iter.Seq[T]) iter.Seq[T] {
	return func(yield func(T) bool) {
		next, stop := iter.Pull(seq)
		defer stop()

		for {
			select {
			case <-ctx.Done():
				return
			default:
				v, ok := next()
				if !ok {
					return
				}
				if !yield(v) {
					return
				}
			}
		}
	}
}

技巧2:并行迭代器

// 并行处理迭代器元素
func ParallelMap[T any, R any](n int, seq iter.Seq[T], transform func(T) R) iter.Seq[R] {
	return func(yield func(R) bool) {
		sem := make(chan struct{}, n)
		results := make(chan R, n)
		done := make(chan struct{})

		go func() {
			defer close(results)
			for v := range seq {
				select {
				case sem <- struct{}{}:
					go func(val T) {
						defer func() { <-sem }()
						select {
						case results <- transform(val):
						case <-done:
						}
					}(v)
				case <-done:
					return
				}
			}
			// 等待所有goroutine完成
			for i := 0; i < cap(sem); i++ {
				sem <- struct{}{}
			}
		}()

		for r := range results {
			if !yield(r) {
				close(done)
				return
			}
		}
	}
}

技巧3:迭代器性能基准

// 基准测试:迭代器 vs 传统for循环
func BenchmarkIteratorFilter(b *testing.B) {
	data := make([]int, 10000)
	for i := range data { data[i] = i }

	b.Run("iterator", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			count := 0
			for v := range Filter(slicesToIter(data), func(n int) bool { return n%2 == 0 }) {
				_ = v
				count++
			}
		}
	})

	b.Run("traditional", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			count := 0
			for _, v := range data {
				if v%2 == 0 {
					_ = v
					count++
				}
			}
		}
	})
}

技巧4:自定义集合实现iter接口

// 自定义集合实现标准迭代器接口
type OrderedMap[K comparable, V any] struct {
	keys   []K
	values map[K]V
}

func NewOrderedMap[K comparable, V any]() *OrderedMap[K, V] {
	return &OrderedMap[K, V]{
		values: make(map[K]V),
	}
}

func (m *OrderedMap[K, V]) Set(key K, value V) {
	if _, exists := m.values[key]; !exists {
		m.keys = append(m.keys, key)
	}
	m.values[key] = value
}

// All 返回按键序的迭代器
func (m *OrderedMap[K, V]) All() iter.Seq2[K, V] {
	return func(yield func(K, V) bool) {
		for _, key := range m.keys {
			if !yield(key, m.values[key]) {
				return
			}
		}
	}
}

// Keys 返回键迭代器
func (m *OrderedMap[K, V]) Keys() iter.Seq[K] {
	return func(yield func(K) bool) {
		for _, key := range m.keys {
			if !yield(key) {
				return
			}
		}
	}
}

// Values 返回值迭代器
func (m *OrderedMap[K, V]) Values() iter.Seq[V] {
	return func(yield func(V) bool) {
		for _, key := range m.keys {
			if !yield(m.values[key]) {
				return
			}
		}
	}
}

技巧5:迭代器中间件模式

// 迭代器中间件:日志、指标、追踪
func WithMetrics[T any](name string, seq iter.Seq[T]) iter.Seq[T] {
	return func(yield func(T) bool) {
		count := 0
		start := time.Now()
		for v := range seq {
			count++
			if !yield(v) {
				log.Printf("[ITER:%s] interrupted after %d items, elapsed: %v", name, count, time.Since(start))
				return
			}
		}
		log.Printf("[ITER:%s] completed %d items, elapsed: %v", name, count, time.Since(start))
	}
}

// 使用
for v := range WithMetrics("user_query", Filter(users, isActive)) {
    process(v)
}

Go迭代器 vs 其他语言对比

维度 Go 1.24 iter Python Generator Rust Iterator Java Stream
类型 func(yield func(V) bool) yield v trait Iterator Stream<T>
泛型 ✅ 完整泛型 ❌ 动态类型 ✅ 完整泛型 ✅ 完整泛型
懒求值 ✅ 天然懒 ✅ 天然懒 ✅ 天然懒 ✅ 可选拉/推
提前退出 ✅ yield返回false ✅ break ✅ take/scan ⚠️ 需短路操作
组合性 ✅ 函数组合 ✅ 生成器组合 ✅ adapter组合 ✅ 流式操作
并发安全 ❌ 非并发安全 ❌ GIL限制 ❌ 非并发安全 ✅ 并行流
性能开销 低(函数调用) 高(解释执行) 零成本抽象 中(装箱/拆箱)
学习曲线 中高
生态成熟度 新(1.23引入) 成熟 成熟 成熟

总结

Go 1.24的range over func迭代器是Go语言表达力的重要提升:

  • 基础模式:理解iter.Seq[T]iter.Seq2[K,V]两种签名,掌握yield返回false的提前退出机制
  • 泛型迭代器:Filter/Map/Reduce/Chunk等工具函数让数据处理像管道一样优雅
  • 树/图遍历:将递归遍历封装为迭代器,可组合、可中断、可复用
  • 迭代器管道:Concat/Interleave/TakeWhile/DropWhile实现数据流组合
  • 生产级模式:分页迭代器、文件流、滑动窗口、带context取消

关键原则:迭代器是消耗性的、非并发安全的、天然懒求值的。理解这三点,就能避免90%的坑。

在线工具推荐

本站提供浏览器本地工具,免注册即可试用 →

#Go 1.24#迭代器#range over func#泛型迭代器#Go新特性#2026#编程语言