Go 从 0 到精通 · 第 04 课:条件判断 if 与 switch
Go 从 0 到精通 · 第 04 课:条件判断 if 与 switch
学习定位:这是整套 Go 教程的第 4 课。
前置要求:已经完成第 3 课,掌握了fmt.Print/Println/Printf的区别、控制台输入、以及显式类型转换。
本课目标:掌握 Go 中if和switch两种条件判断方式,理解 Go 特有的写法和设计思想,能根据不同条件控制程序执行路径。
1. 本课你要解决的核心问题
前三课你写的程序都是"从头到尾顺序执行"的。但真实的程序几乎不可能只有一条执行路径。
你需要搞明白以下几个问题:
if在 Go 里的基本写法和其他语言有什么区别- 什么是
if的初始化语句,为什么 Go 要这样设计 else if和else怎么组合使用switch的基本写法和它在 Go 中的特殊之处- 为什么 Go 的
switch不需要break - 什么时候用
if,什么时候用switch
学完这一课,你的程序就能"做决定"了。
2. if 的基本写法
先看最简单的形式。
2.1 单条件判断
1 | package main |
输出:
1 | 你已经成年了 |
这段代码的意思是:如果 age >= 18 成立,就执行大括号里的代码。
2.2 Go 的 if 和其他语言的区别
如果你来自 Java、C、C++ 等语言,你可能习惯这样写:
1 | if (age >= 18) { |
但 Go 里条件表达式不需要小括号:
1 | if age >= 18 { |
加了括号虽然不会报错,但不符合 Go 的风格。Go 代码格式化工具通常也会帮你去掉多余的括号。
另外一个重要区别:大括号不能省略。
在某些语言里,如果 if 后面只有一行代码,可以不写大括号。Go 不允许这样做:
1 | // 错误写法 |
Go 要求:
- 条件表达式不加括号
- 大括号必须有
- 左大括号
{必须和if在同一行
这三个规则从第一天就要养成习惯。
3. if...else
3.1 基本写法
1 | package main |
输出:
1 | 你还未成年 |
else 表示"否则",当 if 条件不成立时执行。
3.2 else 的位置很重要
Go 要求 else 必须紧跟在上一个 } 后面,写在同一行:
1 | // 正确写法 |
1 | // 错误写法 |
else 换到下一行会导致编译错误。这和 Go 自动插入分号的机制有关:编译器会在 } 后面自动加分号,导致 else 变成了"孤立的关键字"。
你不需要深究原理,只要记住:
} else {必须写在同一行。
4. if...else if...else
当条件不止两种时,用 else if 来添加更多分支。
4.1 基本写法
1 | package main |
输出:
1 | 良好 |
执行逻辑是从上往下依次判断,一旦某个条件成立,就执行对应的代码块,后面的分支不再判断。
4.2 条件判断的顺序很重要
看这个反面例子:
1 | package main |
输出:
1 | 及格 |
虽然 score 是 95,但因为第一个条件 score >= 60 已经成立,程序就直接执行第一个分支,后面的分支不会被检查。
这说明:
条件分支的顺序必须从严格到宽松,否则宽松条件会"吃掉"后面的精确条件。
5. Go 特有的 if 初始化语句
这是 Go if 语句最独特的特性之一,很多其他语言没有。
5.1 基本写法
1 | package main |
输出:
1 | 成年了,年龄是 20 |
注意这里的写法:
1 | if age := 20; age >= 18 { |
分号前面是一个初始化语句(声明变量),分号后面是条件表达式。
5.2 为什么要这样设计
这种写法的核心好处是:限制变量的作用域。
age 只在 if 语句块内部可用,出了 if 就不存在了:
1 | package main |
这样做的好处是:
- 变量不会"泄漏"到不需要它的地方
- 代码更干净
- 后面学到错误处理时,这种写法会非常常见
5.3 最典型的实战用法
在 Go 中,你以后会经常看到这样的代码:
1 | if err := doSomething(); err != nil { |
这里先执行 doSomething(),把返回的错误赋给 err,然后立刻判断 err 是否为 nil。
err 只在这个 if 块里有效,不会污染外部作用域。
你现在先留个印象,等学到函数和错误处理时会大量使用这种模式。
5.4 初始化语句也可以用在 else 中
1 | package main |
输出:
1 | 15 是奇数 |
在 else 分支里,num 依然可用。初始化语句声明的变量在整个 if...else 链中都有效。
6. 条件表达式中的逻辑运算符
在条件判断中,你经常需要组合多个条件。Go 支持以下逻辑运算符:
| 运算符 | 含义 | 示例 |
|---|---|---|
&& |
与(两个都为真才为真) | a > 0 && b > 0 |
| ` | ` | |
! |
非(取反) | !isLogin |
6.1 &&:与
1 | package main |
输出:
1 | 可以进入 |
两个条件都满足时,整体才为 true。
6.2 ||:或
1 | package main |
输出:
1 | 可以享受优惠 |
只要有一个条件满足,整体就为 true。
6.3 !:非
1 | package main |
输出:
1 | 请先登录 |
! 把 false 变成 true,把 true 变成 false。
6.4 组合使用
1 | package main |
当条件比较复杂时,建议用括号明确分组,提高可读性。
7. 嵌套 if
if 里面可以再嵌套 if:
1 | package main |
输出:
1 | 可以入场 |
嵌套 if 有时不可避免,但如果嵌套太深,代码可读性会变差。在实际开发中,Go 社区更推荐"尽早返回"的风格来减少嵌套层级。这个技巧在后面学函数时会详细讲。
8. switch 基本用法
switch 是另一种条件判断方式,适合处理多个离散值的匹配场景。
8.1 最基本的 switch
1 | package main |
输出:
1 | 星期三 |
switch 会从上到下匹配 case,找到匹配的就执行对应代码块。如果没有任何 case 匹配,就执行 default。
8.2 Go 的 switch 不需要 break
这是 Go switch 和很多其他语言最大的区别。
在 C、Java 等语言中,switch 的每个 case 后面通常需要写 break,否则会"穿透"到下一个 case。
Go 的设计是:
每个
case执行完就自动结束,不需要写break。
这意味着:
1 | switch day { |
当 day 为 1 时,只会打印"星期一",不会继续执行"星期二"。
Go 为什么这样设计?因为在实际编程中,"穿透"行为绝大多数时候是程序员忘了写 break 导致的 bug,而不是有意为之。Go 选择了更安全的默认行为。
8.3 如果真的需要穿透:fallthrough
在极少数场景下,如果你确实想让执行"穿透"到下一个 case,可以使用 fallthrough:
1 | package main |
输出:
1 | 匹配到 1 |
fallthrough 会强制执行下一个 case 的代码,不管下一个 case 的条件是否匹配。
但在实际开发中,fallthrough 很少使用。你知道它存在就好,不要养成依赖它的习惯。
9. switch 的多值匹配
一个 case 可以同时匹配多个值,用逗号分隔:
1 | package main |
输出:
1 | 周末 |
这比写多个 case 简洁得多,也比用一堆 || 的 if 更清晰。
10. switch 不写表达式:当 if...else if 用
Go 的 switch 有一个很特别的用法:可以不写匹配表达式。
1 | package main |
输出:
1 | 良好 |
这里 switch 后面没有写表达式,每个 case 后面是一个布尔条件。
这种写法本质上等价于 if...else if...else,但在分支比较多的时候,switch 写法更整齐。
你可以根据个人偏好选择:
- 分支少(2~3 个):
if...else if通常更自然 - 分支多(4 个以上):无表达式
switch更整洁
11. switch 也支持初始化语句
和 if 一样,switch 也可以在前面加一个初始化语句:
1 | package main |
输出:
1 | 15 是奇数 |
num 的作用域只限于这个 switch 语句块内部。
带表达式的 switch 也可以这样写:
1 | package main |
12. switch 匹配字符串
switch 不限于匹配数字,也可以匹配字符串:
1 | package main |
输出:
1 | 你在学习 Go 语言 |
这在处理命令、状态码、配置值等场景时非常实用。
13. if 和 switch 怎么选
这是初学者经常会问的问题。下面给你一个简单的判断标准:
13.1 用 if 的场景
- 条件是范围判断(大于、小于、区间)
- 条件涉及多个不同变量的组合
- 只有 2~3 个分支
- 条件逻辑比较复杂,需要
&&和||
13.2 用 switch 的场景
- 一个变量需要和多个固定值匹配
- 分支比较多(4 个以上)
- 逻辑是"这个值等于什么"的模式
- 希望代码更整齐
13.3 一句话总结
if更灵活,适合复杂条件;switch更整齐,适合多值匹配。
两者没有绝对优劣,根据具体场景选择即可。
14. 一段综合示例
把本课的核心知识串到一个程序里:
1 | package main |
运行效果(输入 85):
1 | 请输入你的成绩(0-100):85 |
运行效果(输入 59):
1 | 请输入你的成绩(0-100):59 |
这个程序里同时用到了 if、if...else、if 初始化语句、无表达式 switch、多值匹配 switch,是本课内容的完整练习。
15. 常见坑总结
15.1 if 条件加了小括号
1 | // 不推荐(Go 风格) |
虽然加括号不报错,但不符合 Go 惯例。
15.2 else 没有紧跟 }
1 | // 错误:编译不通过 |
else 必须和 } 在同一行。
15.3 if...else if 条件顺序写反了
把宽松条件放在前面,会导致精确条件永远无法执行。
1 | // 错误示范 |
条件从严格到宽松排列。
15.4 以为 Go 的 switch 需要 break
不需要。Go 的 switch 每个 case 自动结束。
如果你从其他语言转来,可能会本能地加 break。在 Go 里虽然加了不报错,但完全多余。
15.5 switch 的 case 后面写了重复值
1 | switch day { |
同一个 switch 里,case 的值不能重复。
15.6 fallthrough 的误用
fallthrough 是无条件穿透到下一个 case,它不检查下一个 case 的条件。如果你希望的是"满足某个条件时执行多个分支",fallthrough 可能不是正确的工具。
16. 本课练习
一定要亲手写,不要只看。
练习 1:判断正负零
要求:
- 从控制台读取一个整数
- 判断它是正数、负数还是零
- 用
if...else if...else实现
练习 2:成绩等级判断
要求:
- 从控制台读取一个成绩(0-100)
- 用无表达式
switch输出等级:优秀、良好、中等、及格、不及格 - 加上输入合法性检查
练习 3:季节判断
要求:
- 从控制台读取一个月份(1-12)
- 用
switch多值匹配判断季节- 3, 4, 5 → 春季
- 6, 7, 8 → 夏季
- 9, 10, 11 → 秋季
- 12, 1, 2 → 冬季
- 非法月份输出提示
练习 4:体验 if 初始化语句
要求:
- 用
if初始化语句的写法,在if里声明一个变量 - 在
if和else中都使用这个变量 - 尝试在
if语句块外面访问它,观察编译器报什么错
练习 5:简易菜单系统
要求:
- 打印一个菜单(1: 查看余额 2: 存款 3: 取款 4: 退出)
- 读取用户输入的选项
- 用
switch根据选项输出不同的提示文字 - 非法选项输出"无效操作"
练习 6:闰年判断
要求:
- 从控制台读取一个年份
- 判断它是否是闰年
- 闰年规则:能被 4 整除但不能被 100 整除,或者能被 400 整除
- 用
if结合逻辑运算符实现
提示:用 % 取余运算符。
17. 自测题
不看文档,试着回答:
17.1 概念题
- Go 的
if条件表达式需要加小括号吗? else为什么必须紧跟在}后面?if初始化语句的作用是什么?它声明的变量作用域是什么?- Go 的
switch需要写break吗?为什么? fallthrough是做什么的?它检查下一个case的条件吗?- 一个
case可以同时匹配多个值吗?怎么写? switch后面不写表达式时,行为是什么?if...else if的条件顺序为什么重要?&&和||分别表示什么?- 什么场景适合用
if,什么场景适合用switch?
如果你能流畅回答这些问题,说明这一课你已经真正理解了。
18. 本课总结
这一课你学到的,不只是两种语法结构,而是让程序具备"判断能力"的核心机制。
你现在应该已经理解:
if条件不加括号,大括号不能省略,左大括号必须在同一行else必须紧跟},不能换行if支持初始化语句,用分号和条件分隔,变量作用域限制在if块内- 逻辑运算符
&&、||、!用于组合条件 switch匹配到一个case后自动结束,不需要breakswitch支持多值匹配,用逗号分隔switch不写表达式时,case后面写布尔条件,等价于if...else ifswitch也支持初始化语句fallthrough可以强制穿透,但很少使用
从这一课开始,你的程序已经不再是"直线执行"了,它可以根据不同的输入和状态做出不同的反应。
19. 下一课预告
下一课我们进入:循环结构 for。
会重点讲:
- Go 只有
for一种循环关键字 - 经典三段式
for循环 - 条件式
for(类似其他语言的while) - 无限循环
break和continue的使用for range遍历(先做铺垫)- 循环中的常见坑
学完下一课,你就掌握了 Go 的全部基础控制流,可以写出有判断、有循环的完整逻辑了。





