前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >golang面试基础系列-range的坑(三)

golang面试基础系列-range的坑(三)

作者头像
astraw99
发布2021-09-22 14:45:14
5290
发布2021-09-22 14:45:14
举报
文章被收录于专栏:K8s 系列K8s 系列

在 Go 中,for range 用来遍历 slice, map, chan 等,使用频率很高,但遍历虽好用,却很容易踩坑,且看 demo 如下:

1. 只有一个返回值时,则第一个参数是 index

代码语言:javascript
复制
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)
  }
}

输出结果如下:

代码语言:javascript
复制
0
1
2=============0 a
1 b
2 c

2. 遍历 map 为随机序输出,slice 为索引序输出

代码语言:javascript
复制
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)
  }
}

输出结果如下:

代码语言:javascript
复制
ddd DDD
eee EEE
aaa AAA
bbb BBB
ccc CCC
==================
0 aaa
1 bbb
2 ccc
3 ddd
4 eee

3. range v 是值拷贝,且只会声明初始化一次

代码语言:javascript
复制
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)
  }
}

输出结果如下:

代码语言:javascript
复制
0xc00008e020
0xc00008e020
0xc00008e020
zhang &{wang 24}
li &{wang 24}
wang &{wang 24}

正确做法应该是:将 good 部分注释打开,运行结果如下:

代码语言:javascript
复制
0xc00000c080
0xc00000c080
0xc00000c080
li &{li 23}
wang &{wang 24}
zhang &{zhang 22}

小结:for range 遍历注意以上几个小坑:

1. 只有一个返回值时,则第一个参数是index; 2. 遍历 map 为随机序输出,slice 为索引序输出; 3. range v 是值拷贝,且只会声明初始化一次; 掌握以上几点后,就让我们愉快的使用 range 吧~

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-07-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 稻草人生 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档