贝利信息

如何在Golang中使用range遍历数据_range遍历语法说明

日期:2026-01-22 00:00 / 作者:P粉602998670
range遍历切片时v是值副本,修改不影响原切片;遍历map顺序随机,需先排序key才能有序;遍历channel会阻塞至关闭,关闭后自动退出。

range 遍历切片时,v 是值的副本,不是引用

for _, v := range slice 中,v 每次迭代都会被重新赋值为当前元素的拷贝。修改 v 不会影响原切片内容:

nums := []int{1, 2, 3}
for _, v := range nums {
    v = v * 10 // 这行无效:只改了 v 的副本
}
// nums 仍是 [1, 2, 3]

若需修改原切片,必须通过索引访问:

range 遍历 map 时,遍历顺序不保证且每次不同

Go 规范明确要求 range 遍历 map 的顺序是随机的——这不是 bug,而是设计选择,用于防止程序依赖隐式顺序。

常见误判场景:

若需有序遍历,得先提取 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])
}

range 遍历 channel 会阻塞直到有数据或 channel 关闭

for v := range ch 是典型的消费模式,但行为容易被低估:

安全做法:

range 在字符串上遍历的是 rune,不是 byte

Go 字符串底层是 UTF-8 字节数组,但 range 会自动解码为 Unicode 码点(rune):

s := "你好"
for i, r := range s {
    fmt.Printf("index=%d, rune=%U\n", i, r)
    // 输出:
    // index=0, rune=U+4F60
    // index=3, rune=U+597D
}

注意:i 是字节偏移,不是 rune 索引;rrune 类型,不是 byte

实际写 range 循环时,最常忽略的是「谁拥有数据所有权」和「谁控制生命周期」——切片的底层数组、map 的并发安全性、channel 的关闭时机、字符串的编码边界,都藏在看似简单的语法糖下面。