一文熟悉 Go 的循环结构 —— for 循环

news2024/11/29 20:48:15

哈喽大家好,我是陈明勇,今天分享的知识是 Go 的循环结构。如果本文对你有帮助,不妨点个赞,如果你是 Go 语言初学者,不妨点个关注,一起成长一起进步,如果本文有错误的地方,欢迎指出!

耐心和持久胜过激烈和狂热。

循环结构

循循环结构是指在程序中需要反复执行某个功能而设置的一种程序结构。有的编程语言,包含两种循环结构,一种是 for 循环,另一种是 while 循环,而在 Go 里面,有且只有一种循环 —— for 循环。接下来看一个示例:

func main() {
	sum := 0
	for num := 1; num <= 10; num++ {
		sum += num
	}
	println(sum) // 55
}

在这里插入图片描述

上述代码实现的功能是在 1-10 之中累加求和,最后的结果为 55

  • 上图所示,for 循环分为四个部分,第一部分 num := 1 为循环前置语句,在这一部分,我们一般都会定义一些变量,这些变量被使用于第二部分第三部分里。
  • 第二部分是条件判断表达式,也就是布尔表达式,多条件可以使用逻辑操作符进行连接。此部分的作用是判定循环是否继续下去,图中循环不终止的条件为 num <= 10。只要条件成立,就会去执行第三部分.
  • 第三部分为循环体,只要循环不终止,程序就会重复执行循环体里面的代码。上述例子中,循环体所做的事情就是累加 num 变量的值。
  • 第四部分为循环后置语句,这一部分通常会对第一部分所定义的变量进行更新,例如上述例子中,对 num 进行自增。

for 循环执行顺序是这样的:

  • 第一部分(只会执行一次)
  • 第二部分(若布尔表达式的值为 false 则终止循环,不进行第三第四部分)
  • 第三部分
  • 第四部分,然后返回第二部分继续执行。
    对于上述四个部分,除了第三部分以外,其他部分都可以省略。如果只留第三部分,那么就形成死循环,以下为示例:
    func main() {
    	for {
    		println("糟糕,死循环!")
    	}
    }
    
    在一些场景下,我们会利用死循环去做一些特定的事,但是最终还是要跳出死循环的。如何跳出死循环,就涉及到接下来要讲的关键字 break

for-range

除了上面所讲的普通 for 循环的形式,Go 里面还支持一种 for 循环,为 for-range 循环,这是一种什么循环形式呢?我们来看看例子:

import "fmt"

func main() {
	nums := [4]int{1, 2, 3, 4}
	for i := 0; i < len(nums); i++ {
		fmt.Printf("下标:%d,元素:%d\n", i, nums[i])
	}
}

上述代码,在循环前置语句中,声明数组的下标,然后循环体通过下标值打印数组的元素,我们来看看使用 for-range 的代码实现是怎么样的:

import "fmt"

func main() {
	nums := [4]int{1, 2, 3, 4}
	for i, num := range nums {
		fmt.Printf("下标:%d,元素:%d\n", i, num)
	}
}

与普通 for 循环相比,for-range 的形式代码量少了很多,除了循环体保留了下来,其余部分都融入到了 for-range 的语义里。上述代码中,变量 i 为数组的下标索引,num 为数组中的元素值。如果我们所关注的只是数组的下标索引或者元素值,可以进行以下改造:

  • 只关注下标索引
    import "fmt"
    
    func main() {
    	nums := [4]int{1, 2, 3, 4}
    	for i := range nums {
    		fmt.Printf("下标:%d\n", i)
    	}
    }
    
    
    仅仅定义一个 i 变量。
  • 只关注元素值
    import "fmt"
    
    func main() {
    	nums := [4]int{1, 2, 3, 4}
    	for _, num := range nums {
    		fmt.Printf("元素值:%d\n", num)
    	}
    }
    
    
    索引位置使用 _ 代替,表示忽略下标索引的接收。
  • 下标索引和元素值都不关注
    package main
    
    func main() {
    	nums := [4]int{1, 2, 3, 4}
    	for range nums {
    	}
    }
    
    

break 和 continue 关键字

break 和 continue 关键字用于控制 for 循环的代码流程,且只对最近的 for 循环有效(多层循环的情况下)。

  • break
    退出 for 循环,循环体后续代码不再执行。
  • continue
    终止本轮循环,循环体后续代码不再执行,进入下一轮循环。

示例

  • 循环遍历数组,如果在数组内找到元素值 6,则退出循环。
    func main() {
    	nums := [5]int{1, 2, 6, 3, 4}
    	for _, num := range nums {
    		if num == 6 {
    			break
    		}
    		println("元素:", num)
    	}
    }
    
    
    执行结果:
    元素: 1
    元素: 2
    
    根据执行结果可知,遍历数组到元素 6 的时候,使用 break 关键字,循环就终止了,后面的元素 34 没有被打印出来。前面所提到的死循环也可以使用 break 关键字跳出循环。
  • 循环遍历数组,只打印奇数,忽略偶数。
    func main() {
    	nums := [5]int{1, 2, 6, 3, 4}
    	for _, num := range nums {
    		if num%2 == 0 {
    			continue
    		}
    		println("元素:", num)
    	}
    }
    
    执行结果:
    元素: 1
    元素: 3
    
    遇到偶数元素,就使用关键字 continue 结束本轮循环,开始下一轮循环。

label

Go 语言中,label 语句的作用是标记跳转的目标。示例说明:
遍历二维数组,找到元素 3 后结束跳出整个循环。

func main() {
	nums := [][]int{
		{1, 2},
		{3, 4},
		{5, 6},
	}
	for i := 0; i < len(nums); i++ {
		println("第", i+1, "轮:")
		for j := 0; j < len(nums[i]); j++ {
			if nums[i][j] == 3 {
				break
			}
			println("元素值:", nums[i][j])
		}
	}
}

执行结果:

第 1 轮:
元素值: 1
元素值: 2
第 2 轮:
第 3 轮:
元素值: 5
元素值: 6

外层循环一共要循环三轮,根据结果可知,使用 break 关键字,并没有跳出整个循环。在第二轮循环之后,进入内层循环,找到元素 4break 关键字只终止了内层循环,外层循环的第三轮还会继续执行,这并不是我们想要的结果。要想达到目标结果,需要结合 label 语句实现:

func main() {
	nums := [][]int{
		{1, 2},
		{3, 4},
		{5, 6},
	}
outerLoop:
	for i := 0; i < len(nums); i++ {
		println("第", i+1, "轮:")
		for j := 0; j < len(nums[i]); j++ {
			if nums[i][j] == 3 {
				break outerLoop
			}
			println("元素值:", nums[i][j])
		}
	}
}

执行结果:

第 1 轮:
元素值: 1
元素值: 2
第 2 轮:

在第一层循环前面,使用 label 语句,用 outerLoop 进行标记,然后在 break 关键字后面加上这个标记,就能实现跳出整个循环。

小结

本文首先介绍了 Go 里面的普通 for 循环,然后由普通 for 循环引出了 for-range 循环,对于数组、切片、Map 等复合数据结构,遍历方式使用 for-range 的形式会更好,特殊的复合数据类型如 Map,遍历方式也只能用 for-range 的形式。本文还提到了 breakcontinuelabel 关键字,通过案例介绍了它们的使用场景。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/41416.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Spring】——10、@PostConstruct注解和@PreDestroy注解

&#x1f4eb;作者简介&#xff1a;zhz小白 公众号&#xff1a;小白的Java进阶之路 专业技能&#xff1a; 1、Java基础&#xff0c;并精通多线程的开发&#xff0c;熟悉JVM原理 2、熟悉Java基础&#xff0c;并精通多线程的开发&#xff0c;熟悉JVM原理&#xff0c;具备⼀定的线…

OpenStack集群部署——Keystone部署(二)

三、Keyston-认证服务 3.1 Keyston介绍 Keyston介绍 补充 3.2 安装时间同步器 ----------------------------------------------------使用chrony安装------------------------------------------------- ####所有节点 #下载安装chrony yum -y install chrony #修改配置…

【心电信号】Simulink胎儿心电信号提取【含Matlab源码 1550期】

⛄一、心电信号简介 0 引言 心电信号是人类最早研究的生物信号之一, 相比其他生物信号更易于检测, 且具有直观的规律。心电图的准确分析对心脏病的及早治疗有重大的意义。人体是一个复杂精密的系统, 有许多不可抗的外界因素, 得到纯净的心电信号非常困难。可以采用神经网络算法…

MongoDB 分片集群

之前说到了主从集群&#xff0c;关于主从集群的搭建以及细节后面会再次分享&#xff0c;这次我们先初步来看看 分片集群 举个例子 例如我们有几百G甚至更多的数据&#xff0c;可是我们只有单个副本集&#xff0c;数据量这么大&#xff0c;网络 IO &#xff0c;CPU &#xff0c…

《深度学习的数学》chap1 神经网络的思想

《深度学习的数学》chap1 神经网络的思想 文章目录1-1 神经网络和深度学习神经网络用神经网络实现的人工智能“人教导机器”类型的人工智能的问题1-2 神经元工作的数学表示整理神经元的工作神经元工作的数学表示点火条件的图形表示1-3 激活函数&#xff1a;将神经元的工作一般化…

开源项目-排班管理系统,考勤管理系统

哈喽&#xff0c;大家好&#xff0c;今天给大家带来一个开源系统-排版管理系统 ​​​​​​​git上搜索可以FinalScheduler-master可以了解详情 也可以通过csdn下载​​​​​​​ 该系统主要用于人员的排班使用&#xff0c;主要用人员管理&#xff0c;排班管理&#xff0c…

Java-ForkJoinPool(线程池-工作窃取算法)

文章目录概述工作窃取算法工作窃取算法的优缺点使用 ForkJoinPool 进行分叉和合并ForkJoinPool使用RecursiveActionRecursiveTaskFork/Join 案例Demo概述 Fork 就是把一个大任务切分为若干个子任务并行地执行&#xff0c;Join 就是合并这些子任务的执行结果&#xff0c;最后得到…

《精神与爱欲》爱源于母性,且超越性别

《精神与爱欲》爱源于母性&#xff0c;且超越性别 赫尔曼黑塞&#xff08;1877-1962&#xff09;&#xff0c;作家&#xff0c;诗人&#xff0c;画家。1877年生于德国&#xff0c;1924年入籍瑞士。1946年获诺贝尔文学奖。被誉为“德国浪漫派的最后一位骑士”。 文章目录《精神与…

扩展函数和运算符重载

扩展函数和运算符重载 扩展函数 扩展函数表示在不改变某个类的源代码的情况下,仍然可以打开这个类,向该类中添加新的函数为了能够更好的理解扩展函数的功能,先来思考一个问题:给定一个字符串,这个字符串由字母,数字,特殊符号组成,我们想要统计这个字符串当中字母的个数可以这…

第十章 开源许可证

软件是一种著作&#xff0c;天然是拥有版权的。很多人会认为放在 Github 上的就是开源软件&#xff0c;既然放了源代码&#xff0c;我就可以随便使用了。其实版权法规定著作是禁止共享的&#xff0c;也就是说没有许可证的软件等于保留版权。虽然源代码公开了&#xff0c;但并不…

GUI编程--PyQt5--QLabel

文章目录QLabel 文本展示QLabel 图片展示QLCDNumberQProgressBarQErrorMessageQProgressDialogQLabel 文本展示 展示文本、富文本、图片、动画。 # 实例化 label QLabel(self) # 设置文本 label.setText("666") # 设置图片 label.setPixmap(QPixmap) label.resize…

[BUG] runtime network not ready: NetworkReady=false reason:NetworkPluginNotRead

1 背景 执行kubectl get node是发现节点是NotReady状态&#xff0c;接着执行kubectl describe node 节点名 详细查看NotReady状态原因如下&#xff1a; runtime network not ready: NetworkReadyfalse reason:NetworkPluginNotReady message:docker: network plugin is not r…

数据结构之线性表中的双向循环链表【详解】

前言&#xff1a; 嗯&#xff01;昨天我们的无头单向非循环链表咱已经是可以顺利完成出来了的&#xff0c;今天我们就来看一下什么是有头双向循环链表&#xff0c;不要看着这个链表又双向又循环的就比单向不循环链表难&#xff0c;其实这个更加的简单哦&#xff01;前提是你有…

SpringBoot SpringBoot 原理篇 1 自动配置 1.17 自动配置原理【3】

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 原理篇 文章目录SpringBootSpringBoot 原理篇1 自动配置1.17 自动配置原理【3】1.17.1 看源码了1.17.2 小结1 自动配置 1.…

【STA】(1)引言

目录 1. 纳米级设计 2. 什么是STA 3. 为什么要进行STA 4. 设计流程 5. 不同阶段的STA 6. STA的局限性 1. 纳米级设计 在半导体器件中&#xff0c;金属互连线通常被用来连接电路中的各个部分&#xff0c;进而实现整个芯片。随着制造工艺的进一步缩小&#xff0c;这些互连线…

【电源专题】案例:不导这颗MOS管的原因是在电路上不通用?

本案例发生在MOS管替代料导入时。正常情况下在替代料导入、部品导入的时候,我们需要查看规格书。怎么查找规格书可以看文章【电子通识】芯片资料查询方法 对于一些关键的信息我们要做对比,一般来说要通过列表进行对比。但因为不同的供应商的测试标准不同,有很多是很难对比的…

信号与系统2——LTI

信号与系统2——LTI一、Introduction1. Representation of LTI systems2. Significance of unit impulse二、DT-LTI&#xff1a;Convolution Sum1. Output2. Impulse response of LTI system H3. Convolution sum4. Convolution Sum Evaluation Procedure5. Sequence Convoluti…

Python 数据容器(1) - list(列表)

文章目录什么是数据容器&#xff1f;Python中的数据容器数据容器&#xff1a;list&#xff08;列表&#xff09;基本语法案例演示列表的下标&#xff08;索引&#xff09;列表常用操作list容器操作总结什么是数据容器&#xff1f; 一种可以容纳多份数据的数据类型&#xff0c;容…

算法学习 | 回溯算法之深度优先搜索常见题型练习

目录 岛屿的最大面积 电话号码的字母组合 二进制手表 组合总数 活字印刷 岛屿的最大面积 题目链接&#xff1a;leetcode-695.岛屿的最大面积 示例 输入&#xff1a;grid [[0,0,1,0,0,0,0,1,0,0,0,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,1,1,0,1,0,0,0,0,0,0,0,0],[0,…

线程“八锁“ synchronized到底是对哪个对象加锁?

线程"八锁" synchronized到底是对哪个对象加锁? 习题一 class Number{public synchronized void a(){System.out.println("1");}public synchronized void b(){System.out.println("2");} } public class TestBlock {public static void main(…