range用于遍历数据类型并返回索引和元素,但会复用迭代变量导致闭包陷阱,需通过传参或重新声明变量解决;遍历map无序,字符串时按rune解码而非字节。

在Go语言中,range 是用于遍历数组、切片、字符串、map以及通道(channel)的一种简洁语法。它常被用来替代传统的 for 循环,使代码更清晰易读。但如果不了解其底层机制和语义规则,很容易踩到“坑”。下面详细说明 Go 中 range 的使用方式、规则以及常见误区。
range 可以返回两个值:索引(或键)和对应位置的元素值。第二个值是可选的,你可以只取索引或只取值。
基本语法如下:
for index, value := range slice {
// 处理 index 和 value
}
支持的数据类型包括:
立即学习“go语言免费学习笔记(深入)”;
示例:
nums := []int{10, 20, 30}
for i, v := range nums {
fmt.Println(i, v) // 输出: 0 10, 1 20, 2 30
}
这是 Go 中最容易出错的地方之一:range 使用同一个变量地址来更新迭代变量。
看这个经典例子:
var wg sync.WaitGroup
nums := []int{1, 2, 3}
for i, v := range nums {
wg.Add(1)
go func() {
defer wg.Done()
fmt.Println("index:", i, "value:", v)
}()
}
wg.Wait()
你可能期望输出:
index: 0 value: 1但实际输出可能是:
index: 2 value: 3原因在于:闭包捕获的是变量的引用,而 i 和 v 在每次循环中都被复用。当 goroutine 真正执行时,循环早已结束,i 和 v 已经是最后一次的值。
解决方法有两种:
for i, v := range nums {
wg.Add(1)
go func(idx int, val int) {
defer wg.Done()
fmt.Println("index:", idx, "value:", val)
}(i, v)
}
for i, v := range nums {
i, v := i, v // 创建新的同名变量
wg.Add(1)
go func() {
defer wg.Done()
fmt.Println("index:", i, "value:", v)
}()
}
Go 中 map 的遍历顺序是不保证有序的。即使你插入的顺序固定,每次运行程序输出的顺序也可能不同。
m := map[string]int{"a": 1, "b": 2, "c": 3}
for k, v := range m {
fmt.Println(k, v)
}
输出可能是任意顺序,比如 b 2, a 1, c 3。这并非 bug,而是 Go 故意设计为随机化遍历顺序,防止开发者依赖顺序逻辑。
如果你需要有序遍历,应先将 key 提取出来并排序:
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
fmt.Println(k, m[k])
}
Go 字符串底层是字节数组,但 range 遍历字符串时会自动解码 UTF-8,返回的是 Unicode 码点(rune),而不是单个字节。
str := "你好"
for i, r := range str {
fmt.Printf("index: %d, rune: %c\n", i, r)
}
输出:
index: 0, rune: 你注意:中文字符占 3 个字节,所以第二个字符的索引是 3。如果你想按字节遍历,需转换为 []byte:
for i, b := range []byte(str) {
fmt.Printf("byte index: %d, byte: %x\n", i, b)
}
基本上就这些。掌握 range 的行为特点,尤其是变量复用和闭包陷阱,能避免很多并发和逻辑错误。合理使用 range 可以让代码更简洁,但也别忽视背后的机制。
以上就是Golang如何使用range遍历_Go range遍历规则与坑点解释的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号