【Go自学第三节】Go的范围(Range)用法; for range 时地址是否变化
创始人
2024-06-01 08:51:35

Go 语言中 range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对。

在讲Go语言的range之前,我们先回顾下Python中range的用法

for i in range(3):print(i)

它的输出结果是

1
2
3

 也就是说我们会对range()方法中存在的元素进行迭代,Go语言中也是这样,不过不同的是python range()中参数是基本数据类型通常是整型数字类型,但是Go语言range用于迭代数组、切片或者集合。


for 循环的 range 格式可以对 slice、map、数组、字符串等进行迭代循环。格式如下:

for key, value := range oldMap {newMap[key] = value
}

如果只想读取 key,格式如下:

for key := range oldMap
//或者
for key, _ := range oldMap

如果只想读取 value,格式如下:

for _, value := range oldMap

 举一个例子

package main
import "fmt"func main() {map1 := make(map[int]float32)map1[1] = 1.0map1[2] = 2.0map1[3] = 3.0map1[4] = 4.0// 读取 key 和 valuefor key, value := range map1 {fmt.Printf("key is: %d - value is: %f\n", key, value)}// 读取 keyfor key := range map1 {fmt.Printf("key is: %d\n", key)}// 读取 valuefor _, value := range map1 {fmt.Printf("value is: %f\n", value)}
}

输出结果如下

key is: 4 - value is: 4.000000
key is: 1 - value is: 1.000000
key is: 2 - value is: 2.000000
key is: 3 - value is: 3.000000
key is: 1
key is: 2
key is: 3
key is: 4
value is: 1.000000
value is: 2.000000
value is: 3.000000
value is: 4.000000

 这里Tip一个常见的面试题

Go中for range的时候,地址是否发生变化

因为for range会创建每个元素的副本,而不是返回每个元素的引用,所以它的地址是不会发生变化的。

这里帖出代码来证明

package mainimport "fmt"type girl struct {Name stringAge int
}func main() {gl := make(map[string]*girl)studs := []girl{{Name: "Lili", Age: 23},{Name: "Lucy", Age: 24},{Name: "Han Mei", Age: 21},}for _, v := range studs {gl[v.Name] = &v}for mk, mv := range gl {fmt.Println(mk, "=>", mv.Age)}
}

编译运行的结果是

Lili => 21
Lucy => 21
Han Mei => 21

从结果可得知,for range的时候,地址并没有发生变化。在循环时,会创建一个变量,每次都会把地址赋给同一个变量,导致循环结束后,拷贝的是最后一个元素的地址。

for _, v := range studs {gl[v.Name] = &vfmt.Printf("%s addr: %v\n", v.Name, &v.Age)
}
Lili addr: 0xc0000a4028
Lucy addr: 0xc0000a4028
Han Mei addr: 0xc0000a4028

 有以下两种解决方式:

1、不使用指针作为map的value,同理下面赋值也不使用地址赋值

gl := make(map[string]girl)for _, v := range studs {gl[v.Name] = v}

2、 在每次循环时,创建一个临时变量tem,将v的值赋给tem,相当于copy一个v到tem,再将tem地址传给指针即可

for _, v := range studs {temp := vgl[v.Name] = &temp
}

相关内容

热门资讯

苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
阿西吧是什么意思 阿西吧相当于... 即使你没有受到过任何外语培训,你也懂四国语言。汉语:你好英语:Shit韩语:阿西吧(아,씨발! )日...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...