Go 中数字范围迭代:3 种强大方法

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

为什么“Is there a way to iterate over a range of integers?”这个问题如此流行?

\n\n

如果您曾经从 Python 转到 Go,您一定记得优雅的 for i in range(10):。在 Python 中,它运行得如同钟表般精准。而在 Go 中……情况则略有不同。Stack Overflow 上这个标题的问题获得了数千次浏览——这并非偶然。习惯了高级抽象的开发者,在遇到 Go 极简的语法时,常常会感到困惑。

\n\n

在本文中,我们将探讨 Go 中迭代整数范围的所有方法:从经典的 for 循环到现代的实用工具。您将了解哪种方法能实现最佳性能,哪种方法能提升代码可读性。让我们开始吧!

\n\n

方法 #1:经典 for 循环(地道的 Go 写法)

\n\n

Go 是一门实用主义的语言。它没有内置的数字 range,但拥有强大的 for 循环。最简单且性能最高的方法是使用三组件循环:

\n\n
package main\n\nimport "fmt"\n\nfunc main() {\n    // 从 0 迭代到 9(共 10 个元素)\n    for i := 0; i < 10; i++ {\n        fmt.Println(i)\n    }\n}
\n\n

这段代码 效率最高:编译器会将其转换为简单的寄存器递增操作。没有内存分配,没有额外开销。这正是 Go 开发者在生产环境中的写法。

\n\n

经典 for 循环的变体

\n\n

您可以轻松更改起始值和步长:

\n\n
// 从 5 到 15\nfor i := 5; i <= 15; i++ {\n    fmt.Println(i)\n}\n\n// 仅偶数,从 0 到 20\nfor i := 0; i <= 20; i += 2 {\n    fmt.Println(i)\n}\n\n// 倒序:从 10 到 1\nfor i := 10; i >= 1; i-- {\n    fmt.Println(i)\n}
\n\n

这种方法是 Go 中数字范围迭代的 黄金标准。它简单、易懂,且无需导入额外的包。

\n\n

方法 #2:使用 range 配合切片(适合 Python 爱好者)

\n\n

如果您非常怀念 Python 风格,可以创建一个切片并通过 range 遍历它。但请小心:这会 严重影响性能。

\n\n
package main\n\nimport "fmt"\n\nfunc main() {\n    // 创建一个从 0 到 9 的整数切片\n    numbers := make([]int, 10)\n    for i := range numbers {\n        numbers[i] = i\n    }\n\n    // 现在使用 range 进行迭代\n    for _, num := range numbers {\n        fmt.Println(num)\n    }\n}
\n\n

为什么这不好?内存分配。每次创建切片时,Go 都会在堆上分配内存。对于 10 个元素的切片,这几乎不可察觉,但对于 1000 万个元素,这就是个问题了。

\n\n

基准测试:for 循环 vs range 配合切片

\n\n

让我们看看数据(迭代 1,000,000 个数字):

\n\n
    \n
  • 经典 for 循环: ~2.5 毫秒,0 次内存分配
  • \n
  • Range 配合切片: ~45 毫秒,1 次内存分配(8 MB)
  • \n
\n\n

差距高达 18 倍!这还只是针对一百万个元素。对于更大的范围,差距只会进一步扩大。

\n\n

方法 #3:使用库(iter、lo 等)

\n\n

Go 社区一直在发展。存在一些第三方库,为范围迭代添加了语法糖。让我们看看两个流行的库:

\n\n

3.1 iter 包(实验性,Go 1.23+)

\n\n

从 Go 1.23 开始,标准库中引入了一个实验性的 iter 包,它允许创建迭代器。虽然它还不稳定,但已经可以使用:

\n\n
package main\n\nimport (\n    "fmt"\n    "iter"\n)\n\nfunc main() {\n    // 创建一个从 0 到 9 的迭代器\n    seq := iter.Seq[int](func(yield func(int) bool) {\n        for i := 0; i < 10; i++ {\n            if !yield(i) {\n                return\n            }\n        }\n    })\n\n    for num := range seq {\n        fmt.Println(num)\n    }\n}

博客

书籍推荐