跳转到内容

Go 迭代器

来自代码酷

Go迭代器[编辑 | 编辑源代码]

迭代器(Iterator)是Go语言中用于遍历集合元素的一种设计模式,它提供了一种统一的方式来访问容器(如数组、切片、映射等)中的元素,而无需暴露底层数据结构。Go语言没有内置的迭代器类型,但可以通过接口和函数式编程模式实现类似功能。

基本概念[编辑 | 编辑源代码]

迭代器的核心思想是将遍历逻辑与数据结构分离,使得遍历过程更加灵活和可复用。在Go中,迭代器通常通过以下方式实现:

  • 使用`for range`循环(内置语法)
  • 实现自定义迭代器接口
  • 使用生成器模式(通过`channel`和`goroutine`)

`for range`循环[编辑 | 编辑源代码]

Go语言为常见集合类型提供了内置的迭代语法:

// 切片迭代
fruits := []string{"apple", "banana", "cherry"}
for index, fruit := range fruits {
    fmt.Printf("%d: %s\n", index, fruit)
}

// 映射迭代
ages := map[string]int{"Alice": 25, "Bob": 30}
for name, age := range ages {
    fmt.Printf("%s is %d years old\n", name, age)
}

输出:

0: apple
1: banana
2: cherry
Alice is 25 years old
Bob is 30 years old

自定义迭代器[编辑 | 编辑源代码]

当需要更复杂的遍历逻辑时,可以定义实现`Iterator`接口的类型:

type Iterator interface {
    Next() (interface{}, bool)  // 返回下一个元素和是否还有元素
}

// 示例:切片迭代器
type SliceIterator struct {
    data  []interface{}
    index int
}

func (it *SliceIterator) Next() (interface{}, bool) {
    if it.index >= len(it.data) {
        return nil, false
    }
    val := it.data[it.index]
    it.index++
    return val, true
}

// 使用示例
func main() {
    iter := &SliceIterator{data: []interface{}{1, "two", 3.0}}
    for val, ok := iter.Next(); ok; val, ok = iter.Next() {
        fmt.Println(val)
    }
}

输出:

1
two
3

生成器模式[编辑 | 编辑源代码]

通过`channel`和`goroutine`可以实现类似Python生成器的惰性迭代器:

func Count(start, end int) <-chan int {
    ch := make(chan int)
    go func() {
        for i := start; i <= end; i++ {
            ch <- i
        }
        close(ch)
    }()
    return ch
}

func main() {
    for num := range Count(1, 5) {
        fmt.Println(num)
    }
}

输出:

1
2
3
4
5

实际应用案例[编辑 | 编辑源代码]

数据库结果集遍历[编辑 | 编辑源代码]

迭代器模式非常适合处理大量数据库记录:

type DBRowIterator struct {
    rows *sql.Rows
}

func (it *DBRowIterator) Next() (map[string]interface{}, bool) {
    if !it.rows.Next() {
        return nil, false
    }
    columns, _ := it.rows.Columns()
    values := make([]interface{}, len(columns))
    for i := range values {
        values[i] = new(interface{})
    }
    it.rows.Scan(values...)
    
    result := make(map[string]interface{})
    for i, col := range columns {
        result[col] = *(values[i].(*interface{}))
    }
    return result, true
}

文件逐行读取[编辑 | 编辑源代码]

处理大文件时避免内存溢出:

type FileLineIterator struct {
    file *os.File
    scanner *bufio.Scanner
}

func (it *FileLineIterator) Next() (string, bool) {
    if it.scanner.Scan() {
        return it.scanner.Text(), true
    }
    return "", false
}

性能考虑[编辑 | 编辑源代码]

迭代器设计需要考虑以下性能因素:

  • 内存使用(避免在迭代期间创建大量临时对象)
  • 并发安全性(是否支持多goroutine同时迭代)
  • 错误处理(迭代过程中可能发生的错误)

graph TD A[开始迭代] --> B{是否有下一个元素?} B -->|是| C[获取下一个元素] C --> D[处理元素] D --> B B -->|否| E[结束迭代]

数学表示[编辑 | 编辑源代码]

迭代器可以形式化表示为: I=(S,N,F) 其中:

  • S 是状态集合
  • N:S{true,false} 判断是否有下一个元素
  • F:S(E,S) 获取下一个元素和更新状态

进阶主题[编辑 | 编辑源代码]

  • 反向迭代器:从后向前遍历集合
  • 过滤迭代器:只返回满足条件的元素
  • 转换迭代器:对每个元素应用转换函数
  • 并发迭代器:安全支持多goroutine访问

通过掌握迭代器模式,Go开发者可以编写出更灵活、更高效的集合处理代码,特别是在处理大数据流或复杂数据结构时。