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

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

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语言 数据结构 循环 错误处理

推荐文章

Rust 并发执行异步操作
2024-11-19 08:16:42 +0800 CST
Vue中的表单处理有哪几种方式?
2024-11-18 01:32:42 +0800 CST
五个有趣且实用的Python实例
2024-11-19 07:32:35 +0800 CST
Vue3中如何处理异步操作?
2024-11-19 04:06:07 +0800 CST
避免 Go 语言中的接口污染
2024-11-19 05:20:53 +0800 CST
Vue3中怎样处理组件引用?
2024-11-18 23:17:15 +0800 CST
XSS攻击是什么?
2024-11-19 02:10:07 +0800 CST
pip安装到指定目录上
2024-11-17 16:17:25 +0800 CST
Vue3中的虚拟滚动有哪些改进?
2024-11-18 23:58:18 +0800 CST
Manticore Search:高性能的搜索引擎
2024-11-19 03:43:32 +0800 CST
MySQL死锁 - 更新插入导致死锁
2024-11-19 05:53:50 +0800 CST
#免密码登录服务器
2024-11-19 04:29:52 +0800 CST
MySQL用命令行复制表的方法
2024-11-17 05:03:46 +0800 CST
介绍 Vue 3 中的新的 `emits` 选项
2024-11-17 04:45:50 +0800 CST
开发外贸客户的推荐网站
2024-11-17 04:44:05 +0800 CST
服务器购买推荐
2024-11-18 23:48:02 +0800 CST
Redis函数在PHP中的使用方法
2024-11-19 04:42:21 +0800 CST
2024年公司官方网站建设费用解析
2024-11-18 20:21:19 +0800 CST
使用 `nohup` 命令的概述及案例
2024-11-18 08:18:36 +0800 CST
Go语言中实现RSA加密与解密
2024-11-18 01:49:30 +0800 CST
解决 PHP 中的 HTTP 请求超时问题
2024-11-19 09:10:35 +0800 CST
程序员茄子在线接单