专栏首页技术面面观三分钟学 Go 语言——range深度解析

三分钟学 Go 语言——range深度解析

小熊最近两天加班比较严重,要处理的事情很多,但是学习的热情永远不会减少,前面讲述的go语言语法是非常非常简单的,所以没有做深入的剖析,后面会从各种角度解析语法,fighting!!

range(范围)

range 关键字在 go 语言中是相当常用好用的语法糖,可以用在 for 循环中迭代 arrayslicemapchannel字符串所有涉及到遍历输出的东西。

基本原理

怎么用?

我们在前一节循环中初次触及到了 range,也知道他可以省略key,或者省略value来循环遍历的特性,但是这种特性要结合实际情况考量该用哪一个。

切片迭代

 nums := []int{1, 2, 3}
 for k, v := range nums {
  fmt.Printf("key: %v , value: %v  \n", k, v)
 }

这和迭代方式非常适合用for-range语句,如果减少赋值,直接索引num[key]可以减少损耗。如下

for k, _:= range nums {

map迭代注意,从 Go1开始,遍历的起始节点就是随机了。

 kvs := map[string]string{
  "a":"a",
  "b":"b",
 }
 for k, v := range kvs {
  fmt.Printf("key: %v , value: %v  \n", k, v)
 }

函数中for-range语句中只获取 key 值,然后跟据 key 值获取 value 值,虽然看似减少了一次赋值,但通过 key 值查找 value 值的性能消耗可能高于赋值消耗。

所以能否优化取决于 map 所存储数据结构特征、结合实际情况进行。

字符串迭代(一个一个的输出字符)

for k,v := range "hello"{
  //注意这里单个字符输出的是ASCII码,
  //用 %c 代表输出字符
  fmt.Printf("key: %v , value: %c
    \n", k, v)
 }

channel (如果不会可以先 mark 下,详细参考后续:go 的并发特性章节)

ch := make(chan int, 10)
 ch <- 11
 ch <- 12

 close(ch) // 不用的时候记得关掉,不关掉又没有另一个goroutine存在会死锁哦,可以注释掉这一句体验死锁

 for x := range ch {
  fmt.Println(x)
 }

结构体

tmp := []struct{
  int
  string
 }{
  {1, "a"},
  {2, "b"},
 }

 for k,v := range tmp{
  fmt.Printf("k:%v, v:%v  \n",k,v)
 }

注意:由于循环开始前循环次数就已经确定了,所以循环过程中新添加的元素是没办法遍历到的。

有可能会遇到的坑!

由于range遍历时value是值的拷贝,如果这个时候遍历上一节声明的结构体时,修改value,原结构体不会发生任何变化!

for _,v := range tmp{
  v.a = 2
 }

两次输出一致

k:0, v:{1 a}  
k:1, v:{2 b}  
k:0, v:{1 a}  
k:1, v:{2 b}  

编程 Tips

  • 遍历过程中可以适情况放弃接收 indexvalue,可以一定程度上提升性能
  • 遍历 channel 时,如果 channel 中没有数据,可能会阻塞
  • 尽量避免遍历过程中修改原数据

总结

  • range可以用于for 循环中迭代 arrayslicemapchannel字符串所有涉及到遍历输出的东西。
  • for-range 的实现实际上是C风格的for循环
  • 使用index,value接收range返回值会发生一次数据拷贝

如有收获,点个在看,诚挚感谢

本文分享自微信公众号 - 编程三分钟(coding3min),作者:小熊

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-04-18

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 让你的Golang项目在IDE里跑起来(Goland使用入门-GOROOT、GOPATH、src、 pkg、bin...)

    每次新建项目,不熟悉go的项目结构,一般跑都跑不起来,每次都要重新搞一遍,好几回跑项目都会报类似File is invalid的错误

    机智的程序员小熊
  • 边做算法边学go语言之LeetCode1160:拼写单词

    题目位置:https://leetcode-cn.com/problems/find-words-that-can-be-formed-by-character...

    机智的程序员小熊
  • Go语言中的数组和切片 len cap append copy

    类比c语言,一个int型数组int a[10],a的类型是int*,也就是整型指针,而c语言中可以使用malloc()动态的分配一段内存区域,c++中可以用ne...

    机智的程序员小熊
  • python从txt文件读取数据

      (作为一个python初学者,记录一点学习期间的笔记,方便日后查阅,若有错误或者更加便捷的方法,望指出!)

    py3study
  • JavaNote[002] - 基本数据类型

    char类型用来表示在Unicode编码表中的字符,它占2个字节,可允许有65535个字符,通常用从 '\u0000' 到 '\uFFFF'之间的十六进制值来表...

    Sam Gor
  • 基于maven+ssm的增删改查之批量删除

    将多选id组合成1-2-3-4的形式传给后端,可以发现我们的请求地址是和单个删除是同一个地址,因此要对删除方法进行改造。

    绝命生
  • C++核心准则ES.85:让空语句可见

    https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es8...

    面向对象思考
  • 银行借“大数据”实现POS“秒贷”

    大数据文摘
  • Vim/Neovim 基于 modeline 的多个任意代码执行漏洞分析

    Vim 是从 vi 发展出来的一个文本编辑器。代码补全、编译及错误跳转等方便编程的功能特别丰富,在程序员中被广泛使用,和 Emacs 并列成为类 Unix 系统...

    知道创宇云安全
  • Python中的NLP

    自然语言处理(NLP)是数据科学中最有趣的子领域之一,数据科学家越来越期望能够制定涉及利用非结构化文本数据的解决方案。尽管如此,许多应用数据科学家(来自STEM...

    February

扫码关注云+社区

领取腾讯云代金券