当前位置:首页 > 技术 > 正文内容

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

Lotus2022-11-28 14:17技术

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

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

循环结构

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

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

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

上述代码实现的功能是在 ​​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​​​ 关键字,循环就终止了,后面的元素 ​​3​​​ 和 ​​4​​​ 没有被打印出来。前面所提到的死循环也可以使用 ​​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​​​ 关键字,并没有跳出整个循环。在第二轮循环之后,进入内层循环,找到元素 ​​4​​​,​​break​​​ 关键字只终止了内层循环,外层循环的第三轮还会继续执行,这并不是我们想要的结果。要想达到目标结果,需要结合 ​​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​​​ 的形式。本文还提到了 ​​break​​​、​​continue​​​ 和 ​​label​​ 关键字,通过案例介绍了它们的使用场景。

原文链接

扫描二维码推送至手机访问。

版权声明:本文来源于网络,仅供学习,如侵权请联系站长删除。

本文链接:https://news.layui.org.cn/post/1046.html

分享给朋友:

“一文熟悉 Go 的循环结构 —— for 循环” 的相关文章

源码学习之MyBatis的底层查询原理

导读 本文通过MyBatis一个低版本的bug(3.4.5之前的版本)入手,分析MyBatis的一次完整的查询流程,从配置文件的解析到一个查询的完整执行过程详细解读MyBatis的一次查询流程,通过本文可以详细了解MyBatis的一次查询过程。在平时的代码编写中,发现了MyBatis一个低版本的bug(3.4.5之前的版本),由于现在很多工程中的版本都是低于3.4.5的,因此在这里用一个简单的例...

设计模式之访问者模式

大多数情况下你不需要访问者模式,但当一旦需要访问者模式时,那就是真的需要它了,这是设计模式创始人的原话。可以看出应用场景比较少,但需要它的时候是不可或缺的,这篇文章就开始学习最后一个设计模式——访问者模式。 一、概念理解 访问者模式概念:封装作用于某对象结构中的各元素的操作,它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。 通俗的解释就是,系统中有一些固定结构的对象(元素),在其...

用深度强化学习玩FlappyBird

摘要:学习玩游戏一直是当今AI研究的热门话题之一。使用博弈论/搜索算法来解决这些问题需要特别地进行周密的特性定义,使得其扩展性不强。使用深度学习算法训练的卷积神经网络模型(CNN)自提出以来在图像处理领域的多个大规模识别任务上取得了令人瞩目的成绩。本文是要开发一个一般的框架来学习特定游戏的特性并解决这个问题,其应用的项目是受欢迎的手机游戏Flappy Bird,控制游戏中的小鸟穿过一堆障碍物。本文...

Codeforces Round #822 (Div. 2) A-F

比赛链接 A 题解 知识点:贪心。 注意到任意三根木棍的相等最优解是最长减最小,因此从小到大排序,三个三个取,取最小值。 时间复杂度 \(O(n\log n)\) 空间复杂度 \(O(n)\) 代码 #include <bits/stdc++.h> #define ll long long using namespace std; ll a[307]; bool solve() {...

【大话云原生】负载均衡篇-小饭馆客流量变大了

文章开始之前,我给大家推荐一个人工智能学习网站,首先说我之前是完全不涉及人工智能领域的,但是我尽然看懂了,以后老哥我就要参与人工智能了。如果你也想学习,点击跳转到网站 一、前言 这是《大话云原生》系列的第二篇,第一篇《煮饺子与docker、kubernetes之间的关系》推出之后受到大家的欢迎,很多朋友联系到我给我加油打气,感谢!我会继续写下去! 书接上回介绍了《煮饺子与docker、kubern...

Ruoyi字典源码学习

此文章属于ruoyi项目实战系列 使用目的 什么是字典数据:具体的值(0,1,"Y","N"),对应具体的业务逻辑("男","女","是","否")。 字典数据不应该只写死在代码中,还应存入数据库,通过管理系统来增删改查。 源码分析 ruoyi项目在低于3.7.0的版本中,前端字典功能实现比较简单,每个index.vue页面都请求dict的api,获取数据再加工显示即可。3.7.0之后的版本使...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。