分享
golang面试基础系列-range的坑(三)
热爱coding的稻草 · · 1140 次点击 · · 开始浏览这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。
在 Go 中,for range 用来遍历 slice, map, chan 等,使用频率很高,但遍历虽好用,却很容易踩坑,且看 demo 如下:
1. 只有一个返回值时,则第一个参数是 index
package main
import "fmt"
func main() {
s := []string{"a", "b", "c"}
// 只有一个返回值:则第一个参数是index
for v := range s {
fmt.Println(v)
}
// 两个返回值
for i, v := range s {
fmt.Println(i, v)
}
}
输出结果如下:
0
1
2
=わ=わ=わ=わ=わ=わ=わ=わ=わ=わ=わ=わ=わ
0 a
1 b
2 c
2. 遍历 map 为随机序输出,slice 为索引序输出
package main
import "fmt"
func main() {
m := make(map[string]string)
m["aaa"] = "AAA"
m["bbb"] = "BBB"
m["ccc"] = "CCC"
m["ddd"] = "DDD"
m["eee"] = "EEE"
// range map 为随机序输出
for i, v := range m {
fmt.Println(i, v)
}
fmt.Println("==================")
s := []string{"aaa", "bbb", "ccc", "ddd", "eee"}
// range slice 为索引序输出
for i, v := range s {
fmt.Println(i, v)
}
}
输出结果如下:
ddd DDD
eee EEE
aaa AAA
bbb BBB
ccc CCC
==================
0 aaa
1 bbb
2 ccc
3 ddd
4 eee
3. range v 是值拷贝,且只会声明初始化一次
package main
import "fmt"
func main() {
ParseStudent()
}
type student struct {
Name string
Age int
}
func ParseStudent() {
m := make(map[string]*student)
stus := []student{
{Name: "zhang", Age: 22},
{Name: "li", Age: 23},
{Name: "wang", Age: 24},
}
for _, stu := range stus {
// 都指向了同一个stu的内存指针,为什么?
// 因为 for range 中的 v 只会声明初始化一次
// 不会每次循环都初始化,最后赋值会覆盖前面的
fmt.Printf("%p\n", &stu)
// 1. bad
m[stu.Name] = &stu
// 2. good
/*newStu := stu
m[stu.Name] = &newStu*/
}
for i, v := range m {
fmt.Println(i, v)
}
}
输出结果如下:
0xc00008e020
0xc00008e020
0xc00008e020
zhang &{wang 24}
li &{wang 24}
wang &{wang 24}
正确做法应该是:将 good 部分注释打开,运行结果如下:
0xc00000c080
0xc00000c080
0xc00000c080
li &{li 23}
wang &{wang 24}
zhang &{zhang 22}
小结:for range 遍历注意以上几个小坑:
- 只有一个返回值时,则第一个参数是
index; - 遍历
map为随机序输出,slice为索引序输出; -
range v是值拷贝,且只会声明初始化一次;
掌握以上几点后,就让我们愉快的使用range吧~
稻草人生
有疑问加站长微信联系(非本文作者)
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
关注微信1140 次点击
上一篇:海绵式的吸收知识无益且有害
下一篇:利用 goland 调试你的程序
添加一条新回复
(您需要 后才能回复 没有账号 ?)
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码` - 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传
收入到我管理的专栏 新建专栏
在 Go 中,for range 用来遍历 slice, map, chan 等,使用频率很高,但遍历虽好用,却很容易踩坑,且看 demo 如下:
1. 只有一个返回值时,则第一个参数是 index
package main
import "fmt"
func main() {
s := []string{"a", "b", "c"}
// 只有一个返回值:则第一个参数是index
for v := range s {
fmt.Println(v)
}
// 两个返回值
for i, v := range s {
fmt.Println(i, v)
}
}
输出结果如下:
0
1
2
=わ=わ=わ=わ=わ=わ=わ=わ=わ=わ=わ=わ=わ
0 a
1 b
2 c
2. 遍历 map 为随机序输出,slice 为索引序输出
package main
import "fmt"
func main() {
m := make(map[string]string)
m["aaa"] = "AAA"
m["bbb"] = "BBB"
m["ccc"] = "CCC"
m["ddd"] = "DDD"
m["eee"] = "EEE"
// range map 为随机序输出
for i, v := range m {
fmt.Println(i, v)
}
fmt.Println("==================")
s := []string{"aaa", "bbb", "ccc", "ddd", "eee"}
// range slice 为索引序输出
for i, v := range s {
fmt.Println(i, v)
}
}
输出结果如下:
ddd DDD
eee EEE
aaa AAA
bbb BBB
ccc CCC
==================
0 aaa
1 bbb
2 ccc
3 ddd
4 eee
3. range v 是值拷贝,且只会声明初始化一次
package main
import "fmt"
func main() {
ParseStudent()
}
type student struct {
Name string
Age int
}
func ParseStudent() {
m := make(map[string]*student)
stus := []student{
{Name: "zhang", Age: 22},
{Name: "li", Age: 23},
{Name: "wang", Age: 24},
}
for _, stu := range stus {
// 都指向了同一个stu的内存指针,为什么?
// 因为 for range 中的 v 只会声明初始化一次
// 不会每次循环都初始化,最后赋值会覆盖前面的
fmt.Printf("%p\n", &stu)
// 1. bad
m[stu.Name] = &stu
// 2. good
/*newStu := stu
m[stu.Name] = &newStu*/
}
for i, v := range m {
fmt.Println(i, v)
}
}
输出结果如下:
0xc00008e020
0xc00008e020
0xc00008e020
zhang &{wang 24}
li &{wang 24}
wang &{wang 24}
正确做法应该是:将 good 部分注释打开,运行结果如下:
0xc00000c080
0xc00000c080
0xc00000c080
li &{li 23}
wang &{wang 24}
zhang &{zhang 22}
小结:for range 遍历注意以上几个小坑:
- 只有一个返回值时,则第一个参数是
index; - 遍历
map为随机序输出,slice为索引序输出; -
range v是值拷贝,且只会声明初始化一次;
掌握以上几点后,就让我们愉快的使用range吧~
稻草人生