编程 Golang 中你应该知道的 Range 知识

2024-11-19 04:01:21 +0800 CST views 749

Golang 中你应该知道的 Range 知识

1.1 for range 概述及使用

for range 是 Go 语言中非常常用的循环结构,用于遍历多种数据结构,例如数组、slice、map、字符串以及 channel。通过 for range,可以简洁地获取集合中的索引和值。

基本语法:

for index, value := range collection {}
  • collection: 要遍历的数据结构,如数组、切片、映射、字符串或通道。
  • index: 当前元素的索引,对于映射,索引为键 (key)。
  • value: 当前索引位置的值。

如果不需要索引,可以使用下划线 (_) 忽略:

for _, value := range collection {}

1.2 for range 使用场景

1.2.1 遍历数组

数组是固定大小的序列,for range 可以用于遍历数组的每个元素。

arr := [5]int{10, 20, 30, 40, 50}
for i, v := range arr {
    fmt.Printf("Index: %d, Value: %d\n", i, v)
}

1.2.2 遍历切片

切片是数组的引用,长度可以动态变化。for range 可以用于切片的遍历。

slice := []int{100, 200, 300, 400, 500}
for i, v := range slice {
    fmt.Printf("Index: %d, Value: %d\n", i, v)
}

1.2.3 遍历 map

for range 可以用于遍历 map 中的键值对。

m := map[string]int{"a": 1, "b": 2, "c": 3}
for key, value := range m {
    fmt.Printf("Key: %s, Value: %d\n", key, value)
}

注意map 的遍历顺序是随机的,每次执行可能不同。

1.2.4 遍历字符串

for range 可以逐个字符遍历字符串,并支持 Unicode 字符。

str := "Hello, 世界"
for i, r := range str {
    fmt.Printf("Index: %d, Rune: %c\n", i, r)
}

注意for range 遍历字符串时,处理的是 Unicode 字符(rune),而不是字节。

1.2.5 遍历 channel

for range 可以用于从通道接收数据,直到通道关闭。

ch := make(chan int, 5)
go func() {
    for i := 0; i < 5; i++ {
        ch <- i
    }
    close(ch)
}()

for v := range ch {
    fmt.Println(v)
}

注意

  • 通道必须关闭,否则 for range 会一直阻塞。
  • for range 会在通道关闭后自动退出循环。

1.3 for range 使用中的常见错误

错误示例 1:指针问题

type user struct {
    name string
    age  uint64
}

func main() {
    u := []user{
        {"wesley", 20},
        {"wei", 30},
        {"wesleywei", 40},
    }
    n := make([]*user, 0, len(u))
    for _, v := range u {
        n = append(n, &v)
    }
    fmt.Println(n)
    for _, v := range n {
        fmt.Println(v)
    }
}

在 Go 1.22 之前,输出会是:

[0xc00000c048 0xc00000c048 0xc00000c048]
&{wesleywei 40}
&{wesleywei 40}
&{wesleywei 40}

原因是每次循环都引用了同一个变量 v 的地址。

错误示例 2:闭包问题

func main() {
    var funcs []func()

    for i := 0; i < 3; i++ {
        funcs = append(funcs, func() {
            fmt.Println(i)
        })
    }

    for _, f := range funcs {
        f()
    }
}

在 Go 1.22 之前,输出为:

3
3
3

这是因为闭包捕获的是循环变量 i 的引用,而不是每次的值。

从 Go 1.22 开始,Go 修复了此问题,输出结果为:

0
1
2

1.4 range 的特殊用法

安全删除 map 中的元素

在 Go 中,可以安全地在 for range 循环中删除 map 中的元素。

func main() {
    d := map[string]string{
        "wesley": "wei",
        "medium": "blog",
    }
    for k := range d {
        if k == "wesley" {
            delete(d, k)
        }
    }
    fmt.Println(d)
}

输出:

map[medium:blog]

这种操作在其他语言中(如 Python 或 Java)可能会引发错误或异常。

动态添加 map 中的元素

可以在 for range 遍历 map 时动态添加元素:

func main() {
    t := map[string]string{
        "wesley":  "handsome",
        "wesley1": "handsome1",
        "wesley2": "handsome2",
    }
    for k := range t {
        t["wesley3"] = "handsome3"
        fmt.Printf("%s-%s ", k, t[k])
    }
}

每次执行的结果可能不同,原因是 map 的哈希表特性导致遍历顺序随机。

1.5 总结

for range 是 Go 语言中非常强大的循环结构,可以遍历多种类型的数据结构。通过掌握其使用场景、常见错误和特殊用法,你可以更高效地处理复杂的数据操作。

复制全文 生成海报 编程 Go语言 数据结构 循环 错误处理

推荐文章

Vue3中如何处理WebSocket通信?
2024-11-19 09:50:58 +0800 CST
2025年,小程序开发到底多少钱?
2025-01-20 10:59:05 +0800 CST
File 和 Blob 的区别
2024-11-18 23:11:46 +0800 CST
PHP解决XSS攻击
2024-11-19 02:17:37 +0800 CST
网络数据抓取神器 Pipet
2024-11-19 05:43:20 +0800 CST
api远程把word文件转换为pdf
2024-11-19 03:48:33 +0800 CST
Nginx rewrite 的用法
2024-11-18 22:59:02 +0800 CST
使用 `nohup` 命令的概述及案例
2024-11-18 08:18:36 +0800 CST
JavaScript 实现访问本地文件夹
2024-11-18 23:12:47 +0800 CST
Golang中国地址生成扩展包
2024-11-19 06:01:16 +0800 CST
Vue3中如何扩展VNode?
2024-11-17 19:33:18 +0800 CST
百度开源压测工具 dperf
2024-11-18 16:50:58 +0800 CST
Plyr.js 播放器介绍
2024-11-18 12:39:35 +0800 CST
Linux查看系统配置常用命令
2024-11-17 18:20:42 +0800 CST
Vue3中的Store模式有哪些改进?
2024-11-18 11:47:53 +0800 CST
程序员茄子在线接单