设为首页 加入收藏

TOP

深入探究for...range语句(一)
2023-07-23 13:25:42 】 浏览:52
Tags:for...range 语句

1. 引言

在Go语言中,我们经常需要对数据集合进行遍历操作。对于数组来说,使用for语句可以很方便地完成遍历。然而,当我们面对其他数据类型,如map、string 和 channel 时,使用普通的for循环无法直接完成遍历。为了更加便捷地遍历这些数据类型,Go语言引入了for...range语句。本文将以数组遍历为起点,逐步介绍for...range语句在不同数据类型中的应用。

2. 问题引入

假设我们有一个整数数组,我们想要遍历数组中的每个元素并对其进行处理。在这种情况下,我们可以使用for语句结合数组的长度来实现遍历,例如:

package main

import "fmt"

func main() {
    numbers := [5]int{1, 2, 3, 4, 5}

    for i := 0; i < len(numbers); i++ {
        fmt.Println(numbers[i])
    }
}

在上述代码中,我们定义了一个整数数组numbers,通过普通的for循环遍历了数组并打印了每个元素。然而,当我们遇到其他数据类型时,如mapstring 或者channel时,此时使用for语句将无法简单对其进行遍历。那有什么方式能够方便完成对mapstring等类型的遍历呢?

事实上,go语言中存在for....range语句,能够实现对这些类型的遍历,下面我们来仔细介绍下for...range

3. 基本介绍

在Go语言中,for...range语句为遍历数组、切片、映射和通道等数据结构提供了一种便捷的方式。它隐藏了底层的索引或迭代器等细节,是Go语言为遍历各种数据结构提供的一种优雅而简洁的语法糖,使得遍历操作更加方便和直观。下面仔细简介使用for...range完成对切片, map, channel的遍历操作。

3.1 遍历切片

当使用for...range语句遍历切片时,它会逐个迭代切片中的元素,并将索引和对应的值赋值给指定的变量。示例代码如下:

numbers := [5]int{1, 2, 3, 4, 5}

for index, value := range numbers {
    // 在这里处理 index 和 value
}

其中numbers 是我们要遍历的切片。index 是一个变量,它在每次迭代中都会被赋值为当前元素的索引(从0开始)。value 是一个变量,它在每次迭代中都会被赋值为当前元素的值。

如果只关注切片中的值而不需要索引,可以使用下划线 _ 替代索引变量名,以忽略它:

numbers := []int{1, 2, 3, 4, 5}

for _, value := range numbers {
    fmt.Println("Value:", value)
}

这样,循环体只会打印出切片中的值而不显示索引。

通过for...range语句遍历切片,我们可以简洁而直观地访问切片中的每个元素,无需手动管理索引,使得代码更加简洁和易读。

3.2 遍历map

当使用for...range语句遍历map时,它会迭代映射中的每个键值对,并将键和对应的值赋值给指定的变量。示例代码如下:

students := map[string]int{
    "Alice":   25,
    "Bob":     27,
    "Charlie": 23,
}

for key, value := range students {
    // 在这里处理 key 和 value
}

这里for...range会遍历所有的键值对,无需我们去手动处理迭代器的逻辑,即可完成对map的遍历操作。

3.3 遍历string

当使用for...range语句遍历字符串时,它会逐个迭代字符串中的字符,并将每个字符的索引和值赋值给指定的变量。以下是遍历字符串的示例代码:

text := "Hello, 世界!"

for index, character := range text {
    fmt.Printf("Index: %d, Character: %c\n", index, character)
}

输出结果为:

Index: 0, Character: H
Index: 1, Character: e
Index: 2, Character: l
Index: 3, Character: l
Index: 4, Character: o
Index: 5, Character: ,
Index: 6, Character:  
Index: 7, Character: 世
Index: 10, Character: 界

需要注意的是,Go语言中的字符串是以UTF-8编码存储的,UTF-8是一种变长编码,不同的Unicode字符可能会占用不同数量的字节。而index的值表示每个字符在字符串中的字节索引位置,所以字符的索引位置并不一定是连续的。

这里通过for...range语句遍历字符串,我们可以方便地处理每个字符,无需手动管理索引和字符编码问题,使得处理字符串的逻辑更加简洁和易读。

3.4 遍历channel

当使用for...range语句遍历channel时,它会迭代通道中的每个值,直到通道关闭为止。下面是一个示例代码:

ch := make(chan int)

// 向通道写入数据的例子
go func() {
    ch <- 1
    ch <- 2
    ch <- 3
    close(ch)
}()

// 将输出 1 2 3
for value := range ch {
    fmt.Println("Value:", value)
}

在示例中,我们向通道写入了3个整数值。然后,使用for...range语句遍历通道,从中获取每个值并进行处理。

需要注意的是,如果通道中没有数据可用,for...range语句会阻塞,直到有数据可用或通道被关闭。因此,当通道中没有数据时,它会等待数据的到达。

通过for...range语句遍历通道,可以非常方便得不断从channel中取出数据,然后对其进行处理。

4. 注意事项

for...range语句可以认为是go语言的一个语法糖,简化了我们对不同数据结构的遍历操作,但是使用for...range语句还是存在一些注意事项的,充分了解这些注意事项,能够让我们更好得使用该特性,下面我们将对其来进行叙述。

4.1 迭代变量是会被复用的

当使用for...range循环时,迭代变量是会被复用的。这意味着在每次循环迭代中,迭代变量都将被重用,而不是在每次迭代中创建一个新的迭代变量。

下面是一个简单的示例代码,演示了迭代变量被复用的情况:

package main

import "fmt"

func main() {
        numbers := []int{1, 2, 3, 4, 5}

        for _, value := range numbers {
           go func() {
              fmt.Print(strconv.Itoa(value) + " ")
           }()
        }
}

在上述代码中,我们使用for...range循环遍历切片numbers,并在每次循环迭代中创建一个匿名函数并启动一个goroutine。该匿名函数打印当前迭代的value变量。下面是一个可能的结果:

4 5 5 5 5

出现这个结果的原

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇翻车了,被读者找出 BUG 下一篇【解决一个小问题】golang 的 `-r..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目