• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    浅析Go语言中的Range关键字

    前言

    相信用过Range的朋友们都知道,Go语言中的range关键字使用起来非常的方便,它允许你遍历某个slice或者map,并通过两个参数(indexvalue),分别获取到slice或者map中某个元素所在的index以及其值。

    比如像这样的用法:

    for index, value := range mySlice {
     fmt.Println("index: " + index)
     fmt.Println("value: " + value)
    }

    上面的例子足够清晰的描述了range的用法,实际上在使用range关键字的时候,还有一些需要特别注意的地方,有一些新手很容易入的”坑”。

    为了说明这些”坑”,我们可以从下面这个稍复杂的例子说起:

    type Foo struct {
     bar string
    }
    func main() {
     list := []Foo{
     {"A"},
     {"B"},
     {"C"},
     }
     list2 := make([]*Foo, len(list))
     for i, value := range list {
     list2[i] = value
     }
     fmt.Println(list[0], list[1], list[2])
     fmt.Println(list2[0], list2[1], list2[2])
    }

    在这个例子中,我们干了下面的一些事情:

         1、定义了一个叫做Foo的结构,里面有一个叫bar的field。随后,我们创建了一个基于Foo结构体的slice,名字叫list

         2、我们还创建了一个基于Foo结构体指针类型的slice,叫做list2

         3、在一个for循环中,我们试图遍历list中的每一个元素,获取其指针地址,并赋值到list2中index与之对应的位置。

         4、最后,分别输出list与list2中的每个元素

    从代码来看,理所当然,我们期望得到的结果应该是这样:

    {A} {B} {C}
    {A} {B} {C}

    但是结果却出乎意料,程序的输出是这样的:

    {A} {B} {C}
    {C} {C} {C}

    从结果来看,仿佛list2中的三个元素,都指向了list中的最后一个元素。这是为什么呢?问题就出在上面那一段for…range循环中。

    在Go的for…range循环中,Go始终使用值拷贝的方式代替被遍历的元素本身,简单来说,就是for…range中那个value,是一个值拷贝,而不是元素本身。这样一来,当我们期望用获取元素的指针地址时,实际上只是取到了value这个临时变量的指针地址,而非list中真正被遍历到的某个元素的指针地址。而在整个for…range循环中,value这个临时变量会被重复使用,所以,在上面的例子中,list2被填充了三个相同的指针地址,并且这三个地址都指向value,而在最后一次循环中,value被赋与了{c}的指针地址。因此,list2输出的时候显示出了三个{c}

    同样的,下面的写法,跟for…range的例子如出一辙:

    var value Foo
    for var i := 0; i  len(list); i++ {
     value = list[i]
     list2[i] = value
    }

    如果我们输出list2的三个元素,结果同样是: {C} {C} {C}

    那么,怎样才是正确的写法呢?我们应该用index来访问for…range中真实的元素,并获取其指针地址:

    for i, _ := range list {
     list2[i] = list[i]
    }

    这样,输出list2中的元素,就能得到我们想要的结果({A} {B} {C})了。

    实验代码如下:

    package main
    
    import "fmt"
    
    type Foo struct {
     bar string
    }
    
    func main() {
     list := []Foo{
     {"A"},
     {"B"},
     {"C"},
     }
    
     list2 := make([]*Foo, len(list))
    
     //错误的例子
     for i, value := range list {
     list2[i] = value
     }
    
     //正确的例子
     //for i, _ := range list {
     // list2[i] = list[i]
     //}
    
     fmt.Println(list[0], list[1], list[2])
     fmt.Println(list2[0], list2[1], list2[2])
    }

    了解了range的正确使用姿势,那么我们下面这个例子也能迎刃而解了:

    package main
    import "fmt"
    type MyType struct {
     field string
    }
    func main() {
     var array [10]MyType
     for _, e := range array {
     e.field = "foo"
     }
     for _, e := range array {
     fmt.Println(e.field)
     fmt.Println("--")
     }
    }

    平常写代码最常见的场景,就是我们需要在一个循环中修改被遍历元素的值。比如上面这个例子,我们希望能使用for…range循环,一次性将array中每个元素的field设置为”foo”。同样,因为range值拷贝的缘故,上面的程序什么都不会输出……

    而正确的做法是:

    for i, _ := range array {
     array[i].field = "foo"
    }

    通过index访问每个元素,并修改其field,这样,就能输出一堆”foo”了……

    实验代码如下:

    package main
    
    import "fmt"
    
    type MyType struct {
     field string
    }
    
    func main() {
     var array [10]MyType
    
     for i, _ := range array {
     array[i].field = "foo"
     }
    
     for _, e := range array {
     fmt.Println(e.field)
     }
    }

    总结

    以上就是关于Go语言中Range关键字的全部内容,这篇文章介绍的还是很详细的,相信本文会对大家学习Go语言具有一定的参考价值,如果有疑问大家可以留言交流,小编会尽快给大家回复的,也请大家继续支持脚本之家。

    您可能感兴趣的文章:
    • Mac OS X中设置VIM语法高亮的方法
    • PHP语法自动检查的Vim插件
    • vim配置显示行号和语法高亮 即.vimrc文件的配置
    • 解决vim语法高亮不起作用的方法
    • google 搜索框添加关键字实现代码
    • Go语言开发环境搭建与初探(Windows平台下)
    • ubuntu下搭建Go语言(golang)环境
    • 利用Go语言初步搭建一个web应用的教程
    • go语言环境搭建简述
    • Centos下搭建golang环境及vim高亮Go关键字设置的方法
    上一篇:总结Go语言中defer的使用和注意要点
    下一篇:Go语言如何并发超时处理详解
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    浅析Go语言中的Range关键字 浅析,语言,中的,Range,关键字,