Go关键字--range

range

用于遍历数组,切片,chan,字符串,字典类型变量。通常和for关键字一起使用。

数组,切片,字符串类型变量遍历过程方法是:

// 需要遍历访问的变量名是array
for index,value := range array{
    // index 表示计数器,表示读取到数组中的第几个元素
    // value 表示数组中的值
    fmt.Println(index,value)
}

上边的index是遍历过程中的序号,在平常使用中,如果不需要这个序号,可以不写,也可以用下划线(_)替换,表示丢弃。写法如下:

// 需要遍历访问的变量名是array
for value := range array{
    // value 表示数组中的值
    fmt.Println(value)
}

// 或者写成下边形式

for _,value := range array{
    // value 表示数组中的值
    fmt.Println(value)
}

使用range遍历数组,切片,字符串类型变量时,当接收有两个变量时,第一个变量接收的是序号,第二个变量接收的是值。当接收方只有一个变量时,range返回的是值,没有序号。

在使用range遍历访问map类型变量时,与上边略有差异,因为map主要有key和value组成。所以在range遍历map类型变量时,返回的是key和value值,示例代码如下:

package main

import (
    "fmt"
)

func main() {
    // 定义字典,并初始化字典
    rel := map[string]int{
        "a": 1,
        "b": 2,
        "c": 3,
        "d": 4,
    }
    for key, val := range rel {
        fmt.Println("key 是:", key, "value 是:", val)
    }
}

使用range关键字遍历访问map类型变量rel,依次读取了字典中key以及key对应的value信息。如果只使用一个变量来接收range的返回值,那么range将只返回map类型变量中的key值,写法如下:

package main

import (
    "fmt"
)

func main() {
    // 定义字典,并初始化字典
    rel := map[string]int{
        "a": 1,
        "b": 2,
        "c": 3,
        "d": 4,
    }
    for val := range rel {
        fmt.Println("结果是:", val)
    }
}

输出结果是:

结果是: d
结果是: a
结果是: b
结果是: c

从输出信息可知,range返回一个值的情况下,返回的是map类型变量的key值,没有value值。所以,当range遍历访问map类型变量时,当接收方只有一个变量时,返回的是map类型变量的key值,让接收方有两个参数时,返回的是map类型变量的key和value值,第一个变量接收key值,第二个变量接收key对应的value值。

当使用range遍历访问chan时,只能返回一个值,也就是chan中读取出来的内容。range读取chan类型变量的方法,请看下边示例代码:

package main

import (
    "fmt"
)

func main() {
    var c = make(chan int, 5)

    c <- 1
    c <- 2
    c <- 3
    c <- 4
    c <- 5
    close(c)

    for val := range c {
        fmt.Println(val)
    }

    fmt.Println("chan读取完成")
}

输出信息是:

1
2
3
4
5
chan读取完成

从上边的示例中,定义了一个chan类型变量c,我们称之为通道c,当向通道c中写入5个数字后,就立刻关闭了通道c,而后边的range是在关闭通道c之后进行的,依然能够正确的读取到通道c中的内容,所以关闭通达c后,并不影响range遍历读取通道c中的内容。

range读取通道中的内容时,当通道一直没有关闭时,如果通道中内容已经被读取完成,程序将会进入阻塞状态。要结束这种阻塞状态,可以选择继续向通道写入数据,此时range将会继续遍历读取通道内容;或者选择关闭通道,当通道被关闭后,range遍历读取通道过程并不会立刻停止,它会继续读取通道中内容,直到同道中全部内容读取完成,才会结束读取,退出for循环。

上边讲到,当通道被关闭后,通道中已经写入的内容并不会消失。所以不影响range去读取通道中的内容,那么关闭通道的意义是什么呢?

使用Close关闭通道的目的是不允许向通道中继续写入内容。如果通道被关闭后,仍然继续向通道中写入内容,将会出现异常,异常信息是:

panic: send on closed channel

这个异常只能在运行的时候出现,在编译的时候不会出现。

猜你喜欢

转载自blog.csdn.net/hzwy23/article/details/82681993