Go 语言中的条件判断和for 循环

发布于:2025-06-18 ⋅ 阅读:(18) ⋅ 点赞:(0)

这篇文章已经放到腾讯智能工作台的知识库啦,链接在这里:ima.copilot-Go 入门到入土。要是你有啥不懂的地方,就去知识库找 AI 聊一聊吧。

1、if 条件判断

在 Go 语言中,if 条件判断是一种基本的控制流结构,用于根据条件的真假来执行不同的代码块。其语法简洁明了,易于上手。

1、基础语法

if 语句的基本语法格式如下:


if boolean_expression {

// 当布尔表达式为 true 时,执行这里的代码

}

关键点

  • 条件 boolean_expression 必须是一个结果为布尔值(truefalse)的表达式。

  • 与许多其他语言不同,Go 语言的 if 条件不需要用括号 () 包围,但执行体的花括号 {}必需的

  • 按照 Go 的编码规范,左花括号 { 应当与 if 关键字在同一行。

让我们来看一个判断年龄的简单示例:

image.png

在上面的代码中,因为 age < 18 的结果为 true,所以程序会打印“未成年”。如果将 age 的值改为 22,则条件不成立,if 块内的代码不会被执行。

image.png

2、复合条件

在实际开发中,我们常常需要判断多个条件。这时可以使用逻辑运算符 && (与) 和 || (或) 来构建复合条件。

例如,我们需要同时判断年龄和国籍:

image.png

只有当 age < 18 并且 country == "中国" 这两个条件都为 true 时,判断才会成立。如果其中任何一个条件为 false,整个表达式的结果就是 false

当条件逻辑变得复杂时,可以使用括号 () 来明确分组和优先级,确保逻辑的正确性。

3、嵌套 if

if 语句内部可以包含另一个 if 语句,形成嵌套结构,以实现更复杂的逻辑判断。

image.png

这个嵌套 if 的逻辑与前面使用 && 的复合条件是等价的,但在某些场景下,嵌套结构能让代码层次更分明。

4、if-elseelse if

为了处理条件不成立时的情况,我们可以使用 else。当 if 的条件为 false 时,程序将自动执行 else 块中的代码。

image.png

如果需要处理多个互斥的条件,可以使用 else if 结构。程序会从上到下依次判断,一旦某个 ifelse if 的条件成立,就会执行其对应的代码块,并跳过所有剩余的 else ifelse

image.png

5、最佳实践:if-else if vs. 多个 if

思考以下两种写法,它们在功能上似乎是等价的:

写法一:使用 if-else if-else(推荐)

image.png

写法二:使用多个独立的 if

image.png

为什么推荐写法一?

  1. 逻辑清晰if-else if 结构明确地表达了一系列互斥的条件,阅读代码时能立刻明白这些条件中只有一个会成立。

  2. 性能更优:当 age16 时,写法一在判断 age < 18 成立后,便不再执行后续的 else ifelse 判断。而写法二则会继续执行后续的两个 if 判断,进行了不必要的比较操作。虽然在简单场景下性能差异微乎其微,但在复杂逻辑或循环中,这种差异可能会被放大。

因此,在处理一系列互斥条件时,应优先使用 if-else if-else 结构。

2、for循环基础用法

Go 语言在循环结构的设计上秉持了其一贯的简洁风格,仅提供了 for 这一种循环关键字。这与其他编程语言(如 C, Java, Python)同时提供 forwhile 循环的做法不同。

Go 的设计者认为,for 循环足够灵活,可以完全覆盖 while 循环的所有使用场景。通过省略 for 循环的某些部分,可以轻松模拟出 while 的行为。这种设计减少了语言的关键字数量,使得语法更加统一。

1、for 循环的基础语法

for 循环的标准形式包含三个部分,由分号 ; 分隔,分别对应:初始化语句条件表达式后置语句


for initialization; condition; post {

// 循环体代码

}

  • 初始化语句 (initialization):在循环开始前执行,通常用于声明和初始化一个局部循环变量。

  • 条件表达式 (condition):在每次循环迭代开始前进行求值。如果为 true,则执行循环体;如果为 false,则退出循环。

  • 后置语句 (post):在每次循环迭代结束后执行,通常用于更新循环变量。

if 语句一样,for 循环的条件部分不需要括号。

让我们通过一个打印数字 0 到 2 的例子来了解其用法:

image.png

2、灵活的 for 循环 (模拟 while)

for 循环的三个部分都不是必需的,可以根据需要省略,这使得 for 循环非常灵活,能够轻松模拟 while 循环。

2.1 模拟 while (condition)

通过省略初始化语句和后置语句,只保留条件表达式,for 循环就等同于 while 循环。

image.png

这段代码的执行效果与前一个例子完全相同。

2.2 模拟无限循环 while (true)

如果将三个部分全部省略,就构成了一个无限循环,等效于其他语言中的 while (true)for(;;)。这在需要持续运行的服务或监听事件的场景中非常常见。

PixPin_2025-06-16_08-37-12.gif

在无限循环中,通常需要一个明确的退出条件,可以使用 break 语句来跳出循环。例如,我们可以在循环体内加入一个 if 判断:

image.png

这个例子最终也只会打印 0, 1, 2,然后程序正常结束。这种 for 结合 if-break 的模式是 Go 中实现条件循环的常用方式。

3、for 循环打印 九九乘法表

掌握了 for 循环的基础之后,我们通过两个经典的编程练习来巩固所学知识:计算 1 到 100 的累加和,以及打印九九乘法表。

1、计算 1 到 100 的和

这是一个非常基础的循环应用。我们的思路是:

  • 在循环外部定义一个用于累加求和的变量 sum

  • 使用 for 循环,让循环变量 i 从 1 遍历到 100。

  • 在每次循环中,将当前的循环变量 i 的值累加到 sum 上。

  • 循环结束后,打印 sum 的值。

image.png

代码解析

  • sum := 0:初始化 sum 为 0。这个变量必须在循环外部定义,否则每次循环都会被重置。

  • for i := 1; i <= 100; i++:经典的 for 循环结构,i 的取值范围是 [1, 100]

  • sum += i:这是 Go 中的复合赋值操作符,是 sum = sum + i 的简写形式,代码更简洁。

2、打印九九乘法表

打印九九乘法表需要使用嵌套循环,一个外层循环控制行数,一个内层循环控制列数。

  • 逻辑分析

  • 九九乘法表总共有 9 行。

  • i 行有 i 个表达式。例如,第 2 行有两个(2*1, 2*2),第 5 行有五个。

  • 这表明内层循环的次数是受外层循环的当前变量控制的。

image.png

代码解析

  • 外层循环 for i := 1; i <= 9; i++:控制从第 1 行到第 9 行。

  • 内层循环 for j := 1; j <= i; j++:是关键所在。它控制每一行需要打印的表达式数量。当外层循环 i 为 3 时,内层循环 j 会从 1 循环到 3,从而打印出三个表达式。

  • fmt.Printf:用于格式化输出。%d 是数字的占位符,%-2d 表示输出一个左对齐且至少占 2 个字符宽度的数字,这能让乘法表看起来更整齐。

  • fmt.Println():在内层循环结束后,用于输出一个换行符,以便开始新一行的打印。

4、for range 的循环用法

除了标准的三段式 for 循环,Go 还提供了一种更强大、更便捷的 for range 结构,专门用于遍历各种数据集合,类似其他语言中的 foreachfor range 可以用于遍历字符串数组切片mapchannel

1、for range 的语法

其基本语法格式如下:


for key, value := range collection {

// ...

}

  • collection:表示待遍历的数据集合。

  • key, value:每次循环,for range 会从中 collection 取出一对值,分别赋值给 keyvalue。这对变量的含义取决于被遍历的数据类型。

  • :=:这里必须使用短变量声明,它会为每次循环迭代创建新的 keyvalue 变量。

2、遍历字符串

for range 用于遍历字符串时:

  • key 是每个字符的起始字节索引 (index)。

  • value 是该字符对应的 Unicode 码点 (类型为 rune),而不是字符本身。

image.png

注意value 得到的是原值的拷贝,在循环中修改 value 不会影响原始的 collection

3、for range 的灵活用法

3.1 忽略变量

如果你在循环中不需要 keyvalue,可以使用匿名变量(下划线 _)来忽略它,以避免编译器报“声明但未使用的变量”错误。

image.png

3.2 只接收一个返回值

如果 for range 只接收一个变量,那么该变量接收到的值是 key(对于字符串、数组、切片来说就是索引)。

image.png

4、for range 与不同数据类型的行为

|数据类型|key 的含义|value 的含义|只接收一个变量时|

|—|—|—|—|

|字符串|字节索引 (index)|Unicode 码点 (rune) 的拷贝|key (索引)|

|数组 / 切片|元素索引 (index)|元素值的拷贝|key (索引)|

|Map|map 的键 (key)|map 的值的拷贝|key (map 的键)|

|Channel|(无 key)|从 channel 接收到的值|value (接收到的值)|

5、 处理中文字符

Go 语言的字符串是 UTF-8 编码的字节序列。一个英文字母占 1 个字节,而一个中文字符通常占 3 个字节。

如果使用传统的 for i := 0; i < len(str); i++ 或单返回值的 for range 来遍历包含中文的字符串,由于是按字节索引,会导致中文字符被“撕裂”而产生乱码。

image.png

正确处理中文的方式:

for range 在设计上已经完美地处理了多字节字符。它能自动识别一个完整字符所占的字节数,并正确地返回其 Unicode 码点和起始索引。

5.1 方式一:使用双变量 for range (推荐)

image.png

可以看到,索引值按 3 递增,for range 准确地跳过了每个中文字符的字节。

5.2 方式二:转换为 []rune 切片

如果确实需要在处理中文字符时获得连续的字符索引(0, 1, 2, …),可以先将字符串转换为 rune 切片。

image.png

为了代码的简洁和高效,当需要遍历字符串中的字符时,强烈推荐直接使用 for key, value := range str 的形式

5、continue 和 break 语句

在循环过程中,有时我们需要更精细地控制循环的执行流程,而不是简单地等待循环条件自然结束。Go 语言提供了 breakcontinue 两个关键字来实现这一目标。

1、break:终止循环

break 语句用于立即终止其所在的最内层for 循环。一旦执行 break,程序将跳出循环体,继续执行循环之后的代码。

这在无限循环或需要在满足特定内部条件时提前退出的场景中非常有用。

PixPin_2025-06-16_08-53-56.gif

在上面的例子中,循环会一直进行,直到 round 的值达到 10,if 条件成立,break 语句被执行,从而强制结束这个无限循环。

2、continue:跳过当次迭代

continue 语句用于跳过当前这次循环迭代中尚未执行的代码,并立即进入下一次循环的迭代。

当我们在循环中遇到某个特定条件,不希望执行后续的逻辑,而是想直接开始下一轮时,continue 就派上了用场。

例如,我们想打印 1 到 10,但跳过数字 5:

image.png

在这个例子中,当 i 等于 5 时,continue 语句被触发,它使得当次循环的 fmt.Println(i) 语句被忽略,程序直接跳转到 for 循环的下一次迭代(i++ 之后,i 变为 6)。

6、goto语句 (谨慎使用)

goto 是 Go 语言中的一个跳转语句,它可以让程序无条件地跳转到函数内的指定标签 (label) 处继续执行。

由于 goto 会破坏程序的正常执行流程,过度使用会导致代码逻辑混乱,可读性极差(即所谓的“面条代码”),因此强烈不建议滥用。绝大多数情况下,我们都可以通过 ifforreturn 等结构来更好地实现逻辑。

1、goto 的基本用法

goto 的语法包含两部分:goto label;label:

  1. 定义标签label: 是一个标识符,后跟一个冒号,放置在函数内某行代码的前面。

  2. 执行跳转goto label; 语句会使程序立即跳转到 label: 所在的位置。

一个主要的应用场景是从嵌套的深层循环中一次性跳出。我们知道,break 只能跳出其所在的最内层循环,如果想直接终止所有循环,goto 提供了一种解决方案。

PixPin_2025-06-16_08-59-57.gif

在上面的例子中,当内层循环的 j 首次等于 2 时,goto Over 被执行,程序立即跳出两层循环,直接执行 Over: 标签下的 fmt.Println("任务结束")

2、goto 的合理使用场景

尽管 goto 名声不佳,但在一些特定场景下,合理使用可以简化代码,最常见的便是统一的错误处理

当一个函数中有多个可能出错的步骤,且每个错误都需要进行相似的清理工作时,可以使用 goto 将所有错误处理逻辑集中到一处。

image.png

即便如此,在现代 Go 编程中,使用 defer 语句来处理资源释放通常是更推荐、更清晰的做法。

总而言之,请将 goto 视为一个最后的选择,仅在它能显著简化代码且不降低可读性的罕见情况下考虑使用。

7、switch 语句

switch 是 Go 中一种强大的分支控制语句。它提供了一种比一长串 if-else if 链更清晰、更易读的方式来对一个表达式的多种可能的值进行判断。

1、switch 的基础语法


switch expression {

case value1:

// expression 的值等于 value1 时执行

case value2:

// expression 的值等于 value2 时执行

...

default:

// 所有 case 都不匹配时执行

}

  

  • expression:一个表达式,其结果将与各个 case 的值进行比较。

  • case value:每个 case 定义了一个要比较的值。

  • default:一个可选的子句,当没有任何 case 匹配时执行,类似于 if-else 中的 else

  • 自动 break:与 C 或 Java 不同,Go 的 switch 在每个 case 块的末尾自动包含了一个 break。这意味着一旦匹配到一个 case,执行完其代码后就会退出 switch,不会“掉落”到下一个 case

让我们来看一个根据星期输出对应英文的例子:

image.png

2、switch 的灵活用法

2.1 省略表达式

switch 后面的表达式可以省略。这种形式的 switch 等同于 switch true,每个 case 作为一个独立的布尔表达式进行判断。这使得 switch 可以完全替代 if-else if-else 语句,并且通常更具可读性。

例如,我们可以用它来进行分数等级评定:

image.png

2.2 一个 case 匹配多个值

一个 case 后面可以跟多个值,用逗号分隔。只要表达式的结果匹配其中任意一个值,该 case 就会被执行。

image.png

至此,关于 Go 语言的基础流程控制语句(ifforswitch)及其相关的跳转控制(breakcontinuegoto)就介绍完毕了。掌握它们是编写任何复杂程序的基石。在下一篇的博客中,我们将开始探索 Go 语言更丰富的数据结构。


网站公告

今日签到

点亮在社区的每一天
去签到