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

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

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

推荐文章

如何开发易支付插件功能
2024-11-19 08:36:25 +0800 CST
浏览器自动播放策略
2024-11-19 08:54:41 +0800 CST
Claude:审美炸裂的网页生成工具
2024-11-19 09:38:41 +0800 CST
10个几乎无人使用的罕见HTML标签
2024-11-18 21:44:46 +0800 CST
MyLib5,一个Python中非常有用的库
2024-11-18 12:50:13 +0800 CST
设置mysql支持emoji表情
2024-11-17 04:59:45 +0800 CST
一个有趣的进度条
2024-11-19 09:56:04 +0800 CST
Go语言中的mysql数据库操作指南
2024-11-19 03:00:22 +0800 CST
php curl并发代码
2024-11-18 01:45:03 +0800 CST
Python 微软邮箱 OAuth2 认证 Demo
2024-11-20 15:42:09 +0800 CST
前端项目中图片的使用规范
2024-11-19 09:30:04 +0800 CST
Elasticsearch 的索引操作
2024-11-19 03:41:41 +0800 CST
如何在 Vue 3 中使用 TypeScript?
2024-11-18 22:30:18 +0800 CST
跟着 IP 地址,我能找到你家不?
2024-11-18 12:12:54 +0800 CST
Go 单元测试
2024-11-18 19:21:56 +0800 CST
Vue3 中提供了哪些新的指令
2024-11-19 01:48:20 +0800 CST
Flet 构建跨平台应用的 Python 框架
2025-03-21 08:40:53 +0800 CST
JavaScript中设置器和获取器
2024-11-17 19:54:27 +0800 CST
软件定制开发流程
2024-11-19 05:52:28 +0800 CST
程序员茄子在线接单