golang6 条件循环
if
摘要
本视频详细讲解了go语言中的if条件判断与循环语句。首先介绍了if条件判断的基础用法,包括布尔表达式的格式和逻辑处理。随后通过示例说明了多个条件判断的嵌套使用,以及else和else if的写法。特别强调了在实际应用中需要注意的细节,如逻辑清晰性和比较次数的减少。最后,提及了在实际使用中推荐的使用方式,以提高代码的可读性和效率。
分段总结
折叠
00:01if条件判断概述
1.if条件判断是Go语言中的基本控制结构,用于根据条件执行不同的代码块。 2.if条件判断的语法格式简单,包括if关键字、布尔表达式和后续的代码块。
01:16if条件判断的基本用法
1.判断一个值是否小于20,例如判断变量a是否小于20。 2.判断年龄是否小于18岁,并打印未成年。 3.使用布尔表达式进行条件判断,结果必须为布尔值。 4.简单情况下尽量不使用括号,但复杂情况下可以使用括号分组。
04:17if条件判断的嵌套和else用法
1.if条件判断支持嵌套,可以嵌套多个条件判断。 2.else用法表示条件不满足时执行的代码块,包含所有不满足前面条件的情况。 3.else if用法表示满足其他条件时执行的代码块,可以组合使用多个else if。
07:36if条件判断的实际应用
1.实际应用中,if条件判断的写法可以灵活多变。 2.推荐使用上一种写法,减少不必要的比较次数,提高效率。
一、if条件判断 00:00
1. 基本语法结构 00:18
语法格式:if后接布尔表达式,不需要括号,直接跟花括号代码块
代码规范:函数后必须接花括号不能换行,if语句同理
示例:
if age < 18 {fmt.Println("未成年") }
2. 布尔表达式使用 01:13
1)年龄判断示例 01:19
简单判断
:直接使用比较运算符如
age<18age < 18age<18
多条件组合:可用逻辑运算符如&&连接多个条件
括号使用
:虽然支持带括号写法
(age<18)(age < 18)(age<18)
但不推荐常规使用
示例:
age := 16 if age < 18 {fmt.Println("未成年") // 会执行 }
3. 嵌套条件判断 02:52
1)国家年龄判断 02:57
嵌套结构:if代码块内可再嵌套if语句
应用场景:当需要分层判断条件时使用
示例:
age := 16 country := "中国" if age < 18 {if country == "中国" {fmt.Println("中国未成年") } }
4. else分支使用 05:39
1)成年判断示例 05:58
语法结构:else直接跟随if代码块后
执行逻辑:当if条件不满足时自动执行else块
示例:
age := 20 if age < 18 {fmt.Println("未成年") } else {fmt.Println("成年") // 会执行 }
5. else if分支使用 06:17
1)多条件判断示例 06:38
语法结构:在if和else之间可插入多个else if
执行顺序:按顺序判断,第一个满足条件的分支执行后即退出
示例:
age := 18 if age < 18 {fmt.Println("未成年") } else if age == 18 {fmt.Println("刚好成年") // 会执行 } else {fmt.Println("已成年") }
6. 最佳实践建议 07:36
1)条件判断优化 07:48
性能优化:优先使用if-else if结构而非多个独立if,减少比较次数
代码清晰:嵌套层次不宜过深,复杂条件建议拆分
错误示例:
// 不推荐写法(多次比较) if age < 18 { /*...*/ } if age == 18 { /*...*/ } if age > 18 { /*...*/ }
推荐写法:
if age < 18 {// ... } else if age == 18 {// ... } else {// ... }
注意事项:布尔表达式结果必须为布尔值,不能像其他语言那样使用数字或字符串作为条件
二、知识小结
知识点 核心内容 考试重点/易混淆点 难度系数 if条件判断基础语法 if 布尔表达式 { 执行逻辑 }示例:if age < 18 { fmt.Println("未成年") } 1. Go语言if条件不需要括号2. 必须使用花括号且不能换行 ⭐⭐ 多条件判断 支持&&(且)/ | | (或)逻辑运算符<br>示例:if age<18 && country=="中国"
复杂条件建议用括号分组 ⭐⭐⭐ 嵌套if结构 支持多层嵌套判断示例:if country=="中国" { if age<18 {...} } 嵌套层级不宜超过3层 ⭐⭐⭐⭐ else/else if用法 else处理默认情况else if实现多分支判断示例:if age<18 {...} else if age==18 {...} else {...} 执行效率优于多个独立if判断 ⭐⭐⭐ 最佳实践对比 推荐写法:if-else if-else结构不推荐写法:多个独立if判断 关键差异:1. 比较次数减少50%2. 逻辑更清晰 ⭐⭐⭐⭐ 布尔表达式特性 条件结果必须为布尔值支持变量定义与判断结合:if age:=16; age<18 {...} 与其他语言主要区别:不支持隐式类型转换 ⭐⭐⭐
for
摘要
该视频主要讲述了Go语言中的for循环。Go语言只提供了一种循环结构,即for循环,而没有像其他编程语言那样的while循环。视频详细解释了for循环的语法结构,并通过一个例子演示了如何使用for循环打印一系列数字。此外,视频还提到,虽然for循环在Go语言中是唯一的循环结构,但其灵活性和强大的功能使其能够替代其他编程语言中的多种循环结构。
分段总结
折叠
00:01for循环的基础用法
1.for循环是大多数编程语言中唯一的循环结构,不同于其他语言提供for和while两种循环。 2.Go语言设计之初为了减少关键字,只提供了for循环,认为其可以替代while循环。 3.for循环的写法与其他编程语言类似,包括初始化语句、条件判断和循环逻辑。
01:56for循环的初始化语句
1.初始化语句用于定义循环变量,可以在循环体内定义临时变量,其作用域限于for循环。 2.初始化语句不是必须的,如果循环变量有默认值(如int类型的默认值为0),则可以省略。 3.初始化语句的灵活性使得for循环能够适应不同的循环场景。
04:59for循环的死循环实现
1.通过在循环体内使用sleep函数,可以实现在Go语言中的死循环,类似于while循环。 2.sleep函数的参数为duration类型,本质上是int64,常用time.Second或time.Millisecond指定时间单位。 3.通过比较循环变量的值,可以在for循环中实现类似于while循环的条件判断和退出逻辑。
重点
本视频暂不支持提取重点
一、for循环基础 00:00
1. 循环结构介绍 00:02
1)单一循环结构 00:08
设计理念: Go语言只提供for循环一种循环结构,不同于其他语言同时提供for和while循环
替代方案: for循环通过灵活变通可以完全替代while循环的功能
实践验证: 开发者使用经验表明这种设计不会造成实际编码困难
2)替代while循环 00:26
设计初衷: 为了减少语言关键字数量,Go语言设计时省略了while循环
实际效果: for循环经过简单改造即可实现while循环的所有功能
社区反馈: 该设计在开发者社区中几乎没有负面评价
2. 基本语法格式 01:14
1)初始化语句 01:17
标准格式: for init; condition; post {},其中init为初始化语句
变量作用域: 初始化语句中定义的变量作用域仅限于for循环内部
默认值使用: 可以不写初始化语句,直接使用已定义变量的默认值(如int类型默认为0)
2)后置操作 01:40
灵活省略: 后置操作(post)可以写在循环体内,如i++
分号要求: 即使省略初始化语句,分号仍必须保留
等效写法: for ;i<3;i++与for i<3 {... i++}效果相同
3. 变量作用域 02:02
局部性: 在for循环内定义的变量无法在循环外部访问
生命周期: 循环结束时,内部定义的变量会被自动回收
最佳实践: 推荐在循环内部定义临时变量,避免污染外部作用域
4. 循环控制 02:49
1)死循环实现 04:15
简化形式: 完全省略所有条件表达式for {}即可实现死循环
等效关系: 这种形式完全等效于其他语言的while(true)
常见用途: 常用于需要持续运行的服务或守护进程
2)延时控制 05:13
时间包使用: 通过time.Sleep()函数实现循环间隔
参数类型: 接收time.Duration类型参数,本质是int64
单位说明: 直接使用数字时默认单位为纳秒,通常不推荐
5. 时间单位使用 06:04
1)倍数控制 06:10
预定义常量
:
time.Nanosecond = 1
time.Microsecond = 1000 * Nanosecond
time.Millisecond = 1000 * Microsecond
time.Second = 1000 * Millisecond
倍数设置: 可通过乘法指定时长,如2*time.Second
最佳实践: 总是使用预定义常量而非直接数字,提高可读性
6. 条件退出 07:21
while替代: for i<3 {...}完全等效于while(i<3)
边界注意: 条件表达式要注意包含等于情况,如i<=3
自动退出: 当条件不满足时循环自动终止,无需break
7. 下节预告 07:37
实践应用: 下节课将使用for循环计算1到100的累加和
知识延伸: 会涉及循环与累加变量的配合使用
编程实践: 通过具体案例展示for循环的实际应用场景
二、知识小结
知识点 | 核心内容 | 考试重点/易混淆点 | 难度系数 |
---|---|---|---|
Go语言循环结构设计理念 | Go语言仅保留for循环,通过灵活设计替代while循环功能 | for循环三种表达式非必填 vs 其他语言严格语法要求 | ⭐⭐ |
基础for循环语法 | for 初始化;条件;后续操作{}结构,无需括号 | 作用域限定在循环体内 vs 外部定义变量 | ⭐⭐ |
循环控制灵活性 | 可省略初始化/条件/后续操作任一环节,支持死循环写法 | for {}等效while true的实现方式 | ⭐⭐⭐ |
循环变量作用域 | 循环内定义的变量生命周期限于循环体 | 与外部同名变量的遮蔽效应 | ⭐⭐ |
时间延迟控制 | 使用time.Sleep(time.Second)实现输出间隔 | Duration参数的单位换算(秒/毫秒) | ⭐⭐ |
循环终止条件 | 通过条件表达式控制循环退出,支持前置条件判断 | 与break语句的适用场景对比 | ⭐⭐ |
典型应用场景 | 数字序列打印(0-2)、累加计算预告(1-100)、九九乘法表 | 边界条件处理(包含/不包含临界值) | ⭐⭐⭐ |
forrange
摘要
该视频主要讲述了for循环在Go语言中的用法,特别是for range的用法,它可以方便地遍历字符串、数组、切片、map和channel等数据结构。在遍历字符串时,for range返回的是字符的索引和对应的ASCII值。同时,视频也提到了不同数据结构在for range中的不同表现,如map的key和value。此外,视频还强调了for range的写法灵活性和重要性。总的来说,该视频为观众提供了Go语言中for循环和for range用法的全面介绍。
分段总结
折叠
00:01for循环的介绍
1.for循环是编程中常用的一种控制结构,用于重复执行一段代码。 2.for循环除了基本的用法外,还支持对多种数据结构进行遍历。
00:18for range的用法
1.for range是for循环的一种特殊用法,用于遍历字符串、数组、切片、map和channel等数据结构。 2.for range的语法是for key,value range dataStructure,其中key和value分别是遍历过程中获取的键和值。 3.range关键字后的数据结构可以是字符串、数组、切片、map或channel等。
01:23for range的变量定义
1.在for range循环中,key和value变量的定义使用了特殊的符号:_。 2.这个符号用于定义变量并省略类型声明,使得代码更加简洁。 3.key和value的具体含义取决于遍历的数据结构类型。
02:07字符串的遍历示例
1.使用for range遍历字符串时,key表示字符的索引,value表示字符本身。 2.通过打印key和value,可以观察到遍历过程中索引和字符的对应关系。 3.字符串的本质是字符数组,因此遍历过程中获取的是字符的ASCII码值。
04:56匿名变量的使用
1.在for range循环中,可以使用匿名变量_来忽略不需要的key或value。 2.匿名变量在Go语言中非常常用,用于简化代码并提高可读性。 3.通过使用匿名变量,可以更加灵活地处理遍历过程中的数据。
05:46key和value的作用域
1.在for range循环中,key和value的作用域仅限于循环体内。 2.key和value是循环过程中的临时变量,用于存储当前遍历到的键和值。 3.循环结束后,key和value将被销毁,不会对外部变量产生影响。
09:08中文处理技巧
1.在遍历字符串时,如果包含中文,需要注意中文的处理方式。 2.直接打印索引和值可能会导致乱码问题,需要采用适当的方式进行处理。 3.一种常见的做法是省略key,直接打印value,Go语言会自动处理中文的编码问题。
一、for循环的用法 00:02
基础语法
:for循环包含初始化语句(
y:=1y := 1y:=1
)、条件表达式(
y<=9y <= 9y<=9
)和迭代语句(
y++y++y++
)
嵌套循环:可嵌套使用for循环,如外层控制行数(y),内层控制列数(x)
格式化输出
:使用fmt.Printf打印乘法表,格式为"
%d∗%d=%d\%d * \%d = \%d%d∗%d=%d
"
二、for循环遍历字符串 02:05
1. 遍历字符串的示例 02:36
基本语法:使用for index, value := range name遍历字符串"imooc go"
输出结果:会依次输出每个字符的索引和ASCII码值
字符转换:使用fmt.Printf("\%c", value)可将ASCII码转换为实际字符
2. 字符串遍历的key和value 03:02
索引含义:key代表字符在字符串中的位置索引(从0开始)
值类型:value是该位置字符的ASCII码值,如'i'对应105,'m'对应109
ASCII验证:可通过ASCII码表验证字符编码的正确性
3. 字符串的ASCII码 03:16
编码对照:小写字母'i'的ASCII码为105,'m'为109,'o'为111
打印方法:使用\%c格式化输出可将ASCII码转换为对应字符
4. 打印字符值的方法 03:50
格式化语法:fmt.Printf("\%d,\%c\r\n", index, value)
换行处理:使用\r\n实现回车换行效果
输出效果:会显示"0,i"、"1,m"等索引和字符的对应关系
5. 匿名变量的使用 05:02
忽略索引:使用下划线_忽略不需要的索引变量
语法示例:for _, value := range name只获取字符值
编译要求:Go语言不允许声明未使用的变量,必须使用匿名变量占位
6. key和value的详细解释 06:56
字符串特性
:
key是字符索引
value是字符值的拷贝
省略key时返回的是索引
数组特性
:
key是数组索引
value是索引对应值的拷贝
map特性
:
key是map的键
value是键对应值的拷贝
省略key时返回的是map的值
channel特性
:
只有value没有key
value是channel接收的数据
7. 不同数据类型的for range 07:45
结构差异:不同数据结构在for range中的行为不同
索引访问:可通过name[index]直接访问字符串指定位置的字符
类型安全:编译器会根据数据结构提示正确的key和value类型
值拷贝:value始终是原始值的拷贝,修改不会影响原数据
三、for循环遍历中文处理 10:00
1. for range遍历字符串 10:02
基本语法: for key, value := range collection,主要用于遍历字符串、数组、切片、map和channel
返回值
:
字符串:返回索引(key)和对应字符值的拷贝(value)
数组:返回索引和对应值的拷贝
如果不写key,默认返回索引
2. 中文处理乱码问题 10:14
问题现象: 直接使用for index := range name遍历包含中文的字符串时会出现乱码
原因分析
:
中文字符在UTF-8编码中占3个字节
直接按索引访问会拆分成单个字节处理
示例代码:
3. 正确处理中文的方法 10:25
推荐方法
: 使用
for _, value := range name
直接获取字符值
优势: Go语言内部已处理好UTF-8编码转换
示例:
注意事项: 省略key时,value直接返回正确的Unicode字符
4. 中文字符索引与字节问题 11:04
长度差异
:
len(name)返回的是字节数(示例中为17)
实际中文字符数少于字节数(每个中文占3字节)
索引问题
:
直接使用索引访问会错误拆分中文字符
例如"体"字会被拆成3个无效字节
5. 使用rune切片处理中文 11:51
转换方法
:
nameRune := []rune(name)
将字符串转换为Unicode字符(rune)切片
每个rune对应一个完整字符(包括中文)
长度变化
:
转换后len(nameRune)返回实际字符数
示例中"imooc go体系课"转换为11个rune
6. for循环与rune切片结合使用 12:36
标准遍历方式:
注意事项
:
必须使用转换后的rune切片长度
直接使用原字符串长度会导致索引越界
对比优势
:
相比直接range字符串,可以精确控制遍历过程
适用于需要修改字符的场景
四、知识小结
知识点 | 核心内容 | 易混淆点/注意事项 | 难度系数 |
---|---|---|---|
for循环基础 | for循环用于遍历数据结构,支持多种用法(如for range) | 不同语言中遍历语法可能不同(如Java/PHP的for each) | ⭐⭐ |
for range遍历字符串 | 遍历字符串时,key为索引,value为字符的ASCII码(需转换打印) | 直接打印value会输出ASCII码,需用fmt.Printf格式化输出 | ⭐⭐⭐ |
匿名变量使用 | 若不需要索引,可用_忽略(如for _, value := range name) | 未使用的变量必须用匿名变量替换,否则编译报错 | ⭐⭐ |
省略key的陷阱 | 若省略key,value实际返回索引值而非字符 | 直接打印会输出乱码(需通过name[index]获取字符) | ⭐⭐⭐⭐ |
中文字符处理 | 直接for range可正确处理中文(自动处理多字节字符) | 若用索引遍历需先转为[]rune,否则会截断中文字符 | ⭐⭐⭐⭐ |
不同数据结构的遍历差异 | - 字符串/数组/切片:key为索引- map:key为哈希键- channel:仅value有效 | map遍历顺序随机,channel需结合并发机制 | ⭐⭐⭐⭐ |
值拷贝特性 | for range中的value是原数据的拷贝,修改不影响原数据 | 需通过索引直接修改原数据(如name[index] = newValue) | ⭐⭐⭐ |
goto
摘要
该视频主要讲述了
go to
语句在编程中的用法及其特点。首先,介绍了go to
语句可以实现代码的灵活跳转,但其使用可能导致代码可读性降低和难以维护。其次,通过嵌套循环的例子,展示了break
语句无法满足某些情况下结束整个循环的需求,而go to
语句可以实现这一功能。最后,强调了尽管go to
语句在某些场景下(如错误处理)可能有用,但通常并不建议使用,因为其可能导致代码结构混乱。分段总结
折叠
00:01for循环和break、continue
1.for循环的用法:通过循环变量和循环条件进行迭代。 2.break语句:用于跳出当前循环,结束循环执行。 3.continue语句:用于跳过当前循环的剩余部分,进入下一轮循环。
00:23go to语句的基本用法
1.go to语句的灵活性:可以随意跳转到指定的代码块执行。 2.go to语句的应用场景:主要用于程序错误处理和特定需求的跳转。 3.go to语句的缺点:代码可读性差,使用过多会导致代码难以维护。
01:29嵌套for循环和break的限制
1.嵌套for循环的问题:当使用break跳出内层循环时,外层循环仍然会继续执行。 2.break的限制:只能结束当前循环,无法直接结束外层循环。 3.需求示例:在嵌套for循环中,当某个条件满足时,需要结束整个循环。
03:21go to语句在嵌套循环中的应用
1.go to语句的实现:通过定义标签和go to语句跳转到指定标签。 2.示例代码:在嵌套for循环中,当j=2时,跳转到over标签,结束整个循环。 3.go to语句的效果:实现了在嵌套循环中提前结束整个循环的需求。
05:03go to语句的使用场景
1.程序错误处理:在错误处理中,使用go to语句可以统一跳转到错误处理标签。 2.特定需求跳转:在某些特定场景下,使用go to语句可以简化代码逻辑。 3.避免使用:在正常情况下,不建议随意使用go to语句,以保持代码的可读性和可维护性。
一、for循环的用法 00:01
基本结构: for循环包含初始化语句、条件表达式和迭代语句,格式为 for i:=0; i<5; i++
执行流程: 先执行初始化语句,然后检查条件表达式,为真则执行循环体,最后执行迭代语句
二、break和continue 00:11
break作用: 完全跳出当前循环,终止循环的执行
continue作用: 跳过当前循环剩余代码,直接进入下一轮循环
注意事项: 两者都只能影响当前所在的循环层,在嵌套循环中无法直接跳出外层循环
三、问题引入 01:32
嵌套循环问题: 当需要在内层循环中完全终止外层循环时,break无法满足需求
goto介绍
:
功能: 可以无条件跳转到指定标签处的代码块
缺点: 过度使用会降低代码可读性,许多现代语言已移除该特性
使用建议: 应尽量避免使用,仅在特定场景下作为最后手段
四、for循环嵌套for循环打印案例 02:26
案例结构
:
外层循环: for i:=0; i<5; i++
内层循环: for j:=0; j<4; j++
break限制
:
当内层循环使用break时,仅跳出内层循环
外层循环会继续执行下一轮迭代
goto解决方案
:
可以定义标签并使用goto跳出多层循环
示例中当j==2时,使用goto可以直接跳转到循环外部
五、goto语句的基本用法 03:21
语法结构:通过goto 标签名实现跳转,标签定义格式为标签名:,需放在可执行语句前
示例说明
:
定义over:标签并在嵌套循环中使用goto over跳出
当
j=2j=2j=2
时执行跳转,直接打印"over"并终止后续循环
灵活性:可以跨越多层代码块跳转,但过度使用会导致代码逻辑混乱
1. goto语句使用场景最多的程序错误处理 05:06
主要用途
:在程序出现错误时统一跳转到错误处理代码块
典型场景:多个错误检查点共享同一个错误处理逻辑
使用建议
:
慎用原则:多数情况下应避免使用,可用函数/异常处理替代
适用场景:仅当能显著简化代码结构时才考虑使用
实际应用
:
错误处理标签通常命名为errHandler等明确标识用途的名称
示例中使用的over标签仅为演示目的,实际开发应使用语义化命名
六、知识小结
知识点 | 核心内容 | 考试重点/易混淆点 | 难度系数 |
---|---|---|---|
for循环嵌套 | 讲解嵌套for循环的结构和执行流程 | 注意内层循环和外层循环的变量控制 | ⭐⭐ |
break语句 | 用于立即终止当前循环 | 只能跳出当前层循环,无法跳出嵌套循环 | ⭐⭐ |
continue语句 | 跳过当前循环剩余代码进入下一轮 | 与break的区别在于不终止整个循环 | ⭐⭐ |
go to语句 | 实现代码任意跳转到指定标签位置 | 灵活度过高导致代码可读性差,多数语言已弃用 | ⭐⭐⭐⭐ |
go to使用场景 | 主要用于错误处理时的统一跳转 | 需注意标签定义位置和跳转逻辑 | ⭐⭐⭐ |
循环控制对比 | break/continue仅影响当前循环,go to可跨越多层控制 | 嵌套循环中需特别注意控制范围 | ⭐⭐⭐ |
switch
摘要
该视频主要讲述了Go语言中的顺序语句,特别是switch语句的用法和优势。首先,它解释了顺序语句与if语句的相似之处,但强调顺序语句可以使代码更整洁、可读,并且执行性能更高。接着,通过实例演示了switch语句的语法和用法,特别是在处理条件选择时的便利性。最后,也指出了switch语句的局限性,并鼓励观众探索更灵活的使用方法。
分段总结
折叠
00:01顺序语句概述
1.顺序语句是Go语言中的一种控制结构,用于根据条件的顺序进行执行。 2.顺序语句的语法类似于if语句,但具有更高的执行性能和更好的代码可读性。
01:05switch语法介绍
1.switch语句的基本语法包括switch关键字、条件表达式和case语句。 2.case语句用于匹配条件表达式的值,并执行相应的代码块。 3.default语句用于处理所有不满足case条件的情况。
02:27switch语句示例
1.通过示例讲解了如何使用switch语句进行分数判断和星期几的转换。 2.switch语句提高了代码的可读性和整洁性,使逻辑更加清晰。
05:24switch语句的局限性
1.switch语句在处理精确值匹配时表现良好,但处理区间匹配时较为繁琐。 2.在需要更灵活的逻辑时,可以考虑使用其他方式,如if语句。
06:12switch语句的灵活用法
1.通过示例展示了如何使用switch语句进行分数等级的判断。 2.利用switch语句的区间匹配功能,可以简洁地处理分数范围。
09:59switch语句的总结
1.switch语句是Go语言中一种强大的控制结构,用于根据条件的顺序进行执行。 2.switch语句提高了代码的可读性和执行性能,是开发中常用的功能。
一、Go语言控制结构 00:00
1. Goto语句 00:05
主要用途: 主要用于程序错误处理,当出现错误时统一跳转到标签处处理
语法特点: 通过goto over跳转到over:标签处执行
使用建议: 实际开发中很少使用,但需要了解其语法
示例代码:
for i := 0; i < 5; i++ {for j := 0; j < 4; j++ {if j == 2 {goto over}fmt.Println(i, j)} } over: fmt.Println("over")
2. Switch语法 00:17
基本结构:
switch var1 { case val2:// 代码块 case val3:// 代码块 default:// 默认代码块 }
执行逻辑: 从上到下匹配case,都不匹配时执行default
类型要求: case值必须与switch变量类型一致
优势: 比if语句可读性更好,执行性能更高
1)例题:星期几的英文输出 02:33
实现方式:
day := "星期三" switch day { case "星期一":fmt.Println("Monday") case "星期二":fmt.Println("Tuesday") case "星期三":fmt.Println("Wednesday") case "星期四":fmt.Println("Thursday") default:fmt.Println("UnKnown") }
灵活写法: 可以不写switch变量,直接在case中写条件表达式
switch { case day == "星期一":fmt.Println("Monday") // 其他case... }
2)例题:分数等级判断 06:12
区间判断实现:
score := 60 switch { case score < 60:fmt.Println("E") case score >= 60 && score < 70:fmt.Println("D") case score >= 70 && score < 80:fmt.Println("C") case score >= 80 && score < 90:fmt.Println("B") case score >= 90 && score <= 100:fmt.Println("A") }
执行结果: 60分输出"D",95分输出"A"
3)例题:成绩等级判断 08:47
多值匹配语法:
score := 70 switch score { case 60, 70, 80:fmt.Println("Wow") default:fmt.Println("default") }
执行特点: 当score等于60、70或80时输出"Wow",否则输出"default"
灵活组合: 可以结合区间判断和多值匹配实现复杂逻辑
二、结束 10:07
三、知识小结
知识点 核心内容 考试重点/易混淆点 难度系数 switch语句基础语法 switch关键字+条件表达式,case匹配值,default默认分支 与if语句的替代关系:语法结构差异但功能相似 ⭐⭐ switch典型应用场景 多值精确匹配(如星期转换)、区间判断(如分数评级) 类型一致性要求:case值必须与switch表达式类型匹配 ⭐⭐⭐ 无表达式switch 省略switch后表达式,直接在case中写条件判断 灵活性提升:支持复杂条件逻辑(如score > 60 && score < 70) ⭐⭐⭐⭐ 多条件匹配 单case支持逗号分隔的多值匹配(如case 60,70,80) 与区间判断的区别:离散值VS连续范围 ⭐⭐⭐ 性能优势 编译优化:相比if-else链有更高效的跳转表机制 可读性权衡:复杂条件时可能降低代码直观性 ⭐⭐
Go 语言的条件语句(if
)和循环语句(for
)
是控制程序流程的核心结构。与其他语言相比,Go 的语法更加简洁,去掉了冗余的括号和分号,同时保留了强大的流程控制能力。下面详细讲解这两种语句的用法、特性及最佳实践。
一、条件语句(if
)
if
语句用于根据条件执行不同的代码分支,Go 中的 if
语法简洁且灵活,支持在条件判断前执行一个初始化语句。
1. 基本语法
go
if 条件表达式 {// 条件为 true 时执行 } else if 另一个条件表达式 {// 前一个条件为 false,当前条件为 true 时执行 } else {// 所有条件都为 false 时执行 }
特点:
条件表达式不需要用括号
()
包裹(但表达式本身可以包含括号)代码块必须用大括号
{}
包裹,即使只有一行代码else
和else if
必须与上一个代码块的右大括号}
在同一行(否则会编译错误)
基础示例:
go
package mainimport "fmt"func main() {score := 85// 基本 if-elseif score >= 90 {fmt.Println("优秀")} else if score >= 60 {fmt.Println("及格")} else {fmt.Println("不及格")}// 输出:及格 }
2. 带初始化语句的 if
Go 允许在 if
条件前添加一个初始化语句,用于声明或计算临时变量,语法:
go
if 初始化语句; 条件表达式 {// 代码块 }
初始化语句声明的变量仅在当前 if
代码块(包括 else
/else if
)中有效。
示例:
go
func main() {// 初始化语句:计算平均分并声明变量 avgif avg := (85 + 92 + 78) / 3; avg >= 80 {fmt.Printf("平均分 %d,优秀\n", avg) // 变量 avg 在此处可用} else {fmt.Printf("平均分 %d,良好\n", avg) // else 中也可用}// fmt.Println(avg) // 错误:avg 在此处已超出作用域 } // 输出:平均分 85,优秀
常见用途:
简化代码(将变量声明和条件判断合并)
限制变量作用域(避免污染外部命名空间)
配合错误处理(检查函数返回的
error
):
go
// 示例:检查文件打开错误 if file, err := os.Open("data.txt"); err != nil {fmt.Println("文件打开失败:", err) } else {defer file.Close()fmt.Println("文件打开成功")// 操作文件... }
3. 特殊注意事项
无括号要求:条件表达式周围不需要括号,但逻辑复杂时可加括号提高可读性:
go
if (a > b && c == d) || (e != f) {// 复杂条件加括号更清晰 }
else
位置:else
必须紧跟在if
代码块的}
之后,否则会报错:go
// 错误写法(else 单独成行) if score > 60 {fmt.Println("及格") } else { // 编译错误:syntax error: unexpected else, expecting }fmt.Println("不及格") }// 正确写法(else 与 } 在同一行) if score > 60 {fmt.Println("及格") } else {fmt.Println("不及格") }
二、循环语句(for
)
Go 语言中只有 for
一种循环语句,但通过不同的语法形式,可以实现其他语言中 while
、do-while
等循环的功能,非常灵活。
1. 基本 for 循环(类似 C 语言的 for)
语法:
go
运行
for 初始化语句; 条件表达式; 后置语句 {// 循环体 }
初始化语句:在循环开始前执行一次(通常用于声明循环变量)
条件表达式:每次循环前判断,为
true
则执行循环体后置语句:每次循环体执行后执行(通常用于更新循环变量)
示例:
go
运行
func main() {// 打印 0-4 的数字for i := 0; i < 5; i++ {fmt.Printf("%d ", i)}// 输出:0 1 2 3 4 }
2. 类似 while 的循环(省略初始化和后置语句)
如果省略初始化和后置语句,for
就变成了 while
循环:
go
运行
for 条件表达式 {// 循环体 }
示例:
go
运行
func main() {count := 0// 类似 while (count < 5)for count < 5 {fmt.Printf("%d ", count)count++}// 输出:0 1 2 3 4 }
3. 无限循环(省略所有条件)
如果省略所有三个部分(初始化、条件、后置),for
就变成无限循环,需在循环体内用 break
终止:
go
运行
for {// 循环体(需包含 break 或 return 否则会无限执行) }
示例:
go
运行
func main() {count := 0// 无限循环for {if count >= 5 {break // 满足条件时退出循环}fmt.Printf("%d ", count)count++}// 输出:0 1 2 3 4 }
4. 遍历集合(for range
)
for range
是 Go 中遍历集合的专用语法,支持字符串、数组、切片、map、通道(channel)等。语法:
go
运行
for 索引, 值 := range 集合 {// 循环体 }
对于字符串:索引是字符的字节位置,值是
rune
类型(Unicode 码点)对于数组 / 切片:索引是元素位置,值是元素值
对于map:索引是键(key),值是值(value)
对于通道:只有值,没有索引(接收通道中的数据,直到通道关闭)
示例 1:遍历字符串
go
运行
func main() {s := "hello 世界"// 遍历字符串(每个字符是 rune 类型)for i, c := range s {fmt.Printf("索引 %d: 字符 %c (ASCII码 %d)\n", i, c, c)} }
输出:
plaintext
索引 0: 字符 h (ASCII码 104) 索引 1: 字符 e (ASCII码 101) 索引 2: 字符 l (ASCII码 108) 索引 3: 字符 l (ASCII码 108) 索引 4: 字符 o (ASCII码 111) 索引 5: 字符 (ASCII码 32) 索引 6: 字符 世 (ASCII码 19990) 索引 9: 字符 界 (ASCII码 30028)
(注意:中文字符占 3 个字节,所以索引会跳变)
示例 2:遍历切片和 map
go
运行
func main() {// 遍历切片nums := []int{10, 20, 30}for i, v := range nums {fmt.Printf("切片索引 %d: 值 %d\n", i, v)}// 遍历map(键值对顺序不固定)m := map[string]int{"a": 1, "b": 2}for k, v := range m {fmt.Printf("map键 %s: 值 %d\n", k, v)} }
注意:
遍历中如果不需要索引或值,可用下划线
_
忽略(
_
是 Go 中的空白标识符,用于丢弃不需要的返回值):
go
运行
for _, v := range nums { // 只需要值,忽略索引fmt.Println(v) }
遍历 map 时,每次顺序可能不同(map 是无序的)
遍历字符串时,
for range
会自动处理多字节字符(
rune
),而普通
for
循环按字节遍历:
go
运行
s := "世界" // 普通for循环(按字节遍历,得到3个字节) for i := 0; i < len(s); i++ {fmt.Printf("%x ", s[i]) // 输出:e4 b8 96 e7 95 8c } // for range(按字符遍历,得到2个rune) for _, c := range s {fmt.Printf("%c ", c) // 输出:世 界 }
5. 循环控制语句(break
、continue
、goto
)
Go 提供了三种循环控制语句,用于改变循环的执行流程:
(1)break
:终止当前循环
break
用于立即退出当前循环(不再执行后续迭代):
go
运行
func main() {for i := 0; i < 10; i++ {if i == 5 {break // 当i=5时,终止循环}fmt.Printf("%d ", i)}// 输出:0 1 2 3 4 }
(2)continue
:跳过当前迭代
continue
用于跳过当前循环体的剩余部分,直接进入下一次迭代:
go
运行
func main() {for i := 0; i < 5; i++ {if i%2 == 0 {continue // 跳过偶数}fmt.Printf("%d ", i)}// 输出:1 3 }
(3)goto
:跳转到标签位置
goto
用于跳转到循环内的标签位置,可实现复杂的循环控制(如跳出多层循环):
go
运行
func main() {// 外层循环for i := 0; i < 3; i++ {// 内层循环for j := 0; j < 3; j++ {if i == 1 && j == 1 {goto exitLoop // 跳转到exitLoop标签}fmt.Printf("(%d,%d) ", i, j)}} exitLoop: // 标签定义(需单独成行,后面跟冒号)fmt.Println("\n退出循环") }
输出:
plaintext
(0,0) (0,1) (0,2) (1,0) 退出循环
注意:goto
应谨慎使用,过度使用会导致代码逻辑混乱。
三、最佳实践与常见错误
1. 条件语句的最佳实践
当条件判断涉及函数调用时,避免重复计算:
go
运行
// 不推荐:重复调用 len(s) if len(s) > 0 && s[0] == 'a' { ... }// 推荐:用初始化语句缓存结果 if l := len(s); l > 0 && s[0] == 'a' { ... }
错误处理优先返回(提前退出),减少嵌套层级:
go
运行
// 不推荐:多层嵌套 func doSomething() error {if err := step1(); err == nil {if err := step2(); err == nil {// 业务逻辑return nil} else {return err}} else {return err} }// 推荐:提前返回,减少嵌套 func doSomething() error {if err := step1(); err != nil {return err}if err := step2(); err != nil {return err}// 业务逻辑return nil }
2. 循环语句的常见错误
在循环中修改循环变量的副本:
for range
中的值是元素的副本,修改它不会改变原集合:go
运行
nums := []int{1, 2, 3} for _, v := range nums {v *= 2 // 修改的是副本,原切片不变 } fmt.Println(nums) // 输出:[1 2 3](未改变)// 正确做法:通过索引修改 for i := range nums {nums[i] *= 2 } fmt.Println(nums) // 输出:[2 4 6]
循环中创建 goroutine 引用循环变量:循环变量在每次迭代中会被重用,goroutine 可能捕获到同一个变量的地址:
go
运行
// 错误示例:所有goroutine可能打印相同的i(最后一个值) for i := 0; i < 3; i++ {go func() {fmt.Println(i) // 风险:i是共享变量}() } time.Sleep(time.Second) // 等待goroutine执行// 正确示例:通过参数传递当前值 for i := 0; i < 3; i++ {go func(num int) {fmt.Println(num) // 安全:参数是当前值的副本}(i) } time.Sleep(time.Second)
总结
Go 语言的 if
和 for
语句具有简洁、灵活的特点:
if
支持初始化语句,可在条件判断前声明临时变量,简化代码并限制变量作用域for
是唯一的循环语句,通过不同形式可实现普通循环、while
循环和无限循环for range
专为遍历集合设计,能优雅处理字符串、数组、切片、map 等循环控制可使用
break
(终止)、continue
(跳过)和goto
(跳转)
掌握这些语句的用法,能帮助你编写清晰、高效的 Go 代码,尤其是 for range
遍历和 if
初始化语句的使用,是 Go 语言的特色编程风格。