• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell
您的位置:首页 > 脚本语言 >Golang > 浅析Go语言中的Range关键字

浅析Go语言中的Range关键字

作者:daisy 字体:[增加 减小] 来源:互联网

daisy 通过本文主要向大家介绍了浅析物联网的关键技术,go go power range,go over the range,go range,go语言range等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

前言

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

比如像这样的用法:

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

上面的例子足够清晰的描述了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])
}
</div>

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

     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}
</div>

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

{A} {B} {C}
&{C} &{C} &{C}
</div>

从结果来看,仿佛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
}
</div>

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

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

for i, _ := range list {
 list2[i] = &list[i]
}
</div>

这样,输出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])
}
</div>

了解了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("--")
 }
}
</div>

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

而正确的做法是:

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

通过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)
 }
}
</div>

总结

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

</div>

您可能想查找下面的文章:

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

相关文章

  • golang模板template自定义函数用法示例
  • GO语言基础之数组
  • golang针对map的判断,删除操作示例
  • go语言执行windows下命令行的方法
  • go语言实现顺序存储的栈
  • Go语言中的if条件语句使用详解
  • Go语言使用HTTP包创建WEB服务器的方法
  • Go并发编程实践
  • Go语言基础知识总结(语法、变量、数值类型、表达式、控制结构等)
  • Go语言之自定义集合Set

文章分类

  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell

最近更新的内容

    • GO语言基本数据类型总结
    • 利用Go语言初步搭建一个web应用的教程
    • Go语言中new()和 make()的区别详解
    • Go语言通过Luhn算法验证信用卡卡号是否有效的方法
    • Go语言编程入门超级指南
    • Go语言常见哈希函数的使用
    • Go语言服务器开发之简易TCP客户端与服务端实现方法
    • 服务器端Go程序对长短链接的处理及运行参数的保存
    • Go语言生成素数的方法
    • Go语言中常量定义方法实例分析

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有