为什么“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 极简的语法时,常常会感到困惑。
在本文中,我们将探讨 Go 中迭代整数范围的所有方法:从经典的 for 循环到现代的实用工具。您将了解哪种方法能实现最佳性能,哪种方法能提升代码可读性。让我们开始吧!
方法 #1:经典 for 循环(地道的 Go 写法)
\n\nGo 是一门实用主义的语言。它没有内置的数字 range,但拥有强大的 for 循环。最简单且性能最高的方法是使用三组件循环:
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 遍历它。但请小心:这会 严重影响性能。
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
差距高达 18 倍!这还只是针对一百万个元素。对于更大的范围,差距只会进一步扩大。
\n\n方法 #3:使用库(iter、lo 等)
\n\nGo 社区一直在发展。存在一些第三方库,为范围迭代添加了语法糖。让我们看看两个流行的库:
\n\n3.1 iter 包(实验性,Go 1.23+)
\n\n从 Go 1.23 开始,标准库中引入了一个实验性的 iter 包,它允许创建迭代器。虽然它还不稳定,但已经可以使用:
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}