Go 语言控制结构
条件语句
1. if 语句
// 基本 if 语句
if x > 0 {
fmt.Println("x 大于 0")
}
// if 语句带初始化
if x := 10; x > 0 {
fmt.Println("x 大于 0")
}
// if-else 语句
if x > 0 {
fmt.Println("x 大于 0")
} else {
fmt.Println("x 小于等于 0")
}
// if-else if-else 语句
if x > 0 {
fmt.Println("x 大于 0")
} else if x < 0 {
fmt.Println("x 小于 0")
} else {
fmt.Println("x 等于 0")
}
2. switch 语句
switch 语句是多分支条件语句,比多个 if-else 语句更加清晰和高效。Go 语言的 switch 比其他语言更加灵活,不需要显式的 break 语句来阻止执行下一个 case。
特点:
- 自动 break:每个 case 执行完后会自动退出,不会继续执行下一个 case
- 多条件匹配:一个 case 可以匹配多个值,用逗号分隔
- 表达式匹配:case 可以是表达式而不仅仅是常量
- fallthrough:可以使用 fallthrough 关键字强制执行下一个 case
- 类型 switch:可以用于检查接口变量的具体类型
基本语法:
// 基本 switch 语句
switch x {
case 1:
fmt.Println("x 等于 1")
case 2:
fmt.Println("x 等于 2")
default:
fmt.Println("x 不等于 1 或 2")
}
// 多条件匹配示例
switch day := "星期六"; day {
case "星期六", "星期日":
fmt.Println("周末")
case "星期一", "星期二", "星期三", "星期四", "星期五":
fmt.Println("工作日")
default:
fmt.Println("无效的日期")
}
// 类型 switch 示例
func typeCheck(x interface{}) {
switch v := x.(type) {
case nil:
fmt.Println("x 是 nil")
case int:
fmt.Printf("x 是整数: %d\n", v)
case float64:
fmt.Printf("x 是浮点数: %f\n", v)
case string:
fmt.Printf("x 是字符串: %s\n", v)
case bool:
fmt.Printf("x 是布尔值: %t\n", v)
case []int:
fmt.Printf("x 是整数切片: %v\n", v)
case map[string]int:
fmt.Printf("x 是字符串到整数的映射: %v\n", v)
default:
fmt.Printf("x 是未知类型: %T\n", v)
}
}
// switch 语句带初始化
switch x := 10; x {
case 1:
fmt.Println("x 等于 1")
case 2:
fmt.Println("x 等于 2")
default:
fmt.Println("x 不等于 1 或 2")
}
// 无条件的 switch 语句
switch {
case x > 0:
fmt.Println("x 大于 0")
case x < 0:
fmt.Println("x 小于 0")
default:
fmt.Println("x 等于 0")
}
// fallthrough 语句
switch x {
case 1:
fmt.Println("x 等于 1")
fallthrough // 使用fallthrough会强制执行下一个case,而不会判断下一个case的条件是否满足
// 如果有case 3且case 2也有fallthrough,则会继续执行case 3
// fallthrough只会执行紧跟着的下一个case,除非每个case都使用fallthrough
case 2:
fmt.Println("x 等于 2")
}
循环语句
1. for 循环
// 基本 for 循环
for i := 0; i < 10; i++ {
fmt.Println(i)
}
// 类似 while 的 for 循环
i := 0
for i < 10 {
fmt.Println(i)
i++
}
// 无限循环
for {
fmt.Println("无限循环")
break // 跳出循环
}
// 带 range 的 for 循环
arr := []int{1, 2, 3, 4, 5}
for index, value := range arr {
fmt.Printf("索引:%d,值:%d\n", index, value)
}
// 遍历字符串
str := "Hello"
for index, char := range str {
fmt.Printf("索引:%d,字符:%c\n", index, char)
}
// 遍历映射
m := map[string]int{"a": 1, "b": 2}
for key, value := range m {
fmt.Printf("键:%s,值:%d\n", key, value)
}
2. break 和 continue
// break 语句
for i := 0; i < 10; i++ {
if i == 5 {
break // 跳出循环
}
fmt.Println(i)
}
// continue 语句
for i := 0; i < 10; i++ {
if i == 5 {
continue // 跳过当前迭代
}
fmt.Println(i)
}
// 带标签的 break
// Go语言中的标签(label)可以与break和continue一起使用,用于控制跳出多层循环
// 标签必须放在循环语句的前面,并且以冒号结尾
// 使用break配合标签可以直接跳出指定的外层循环,而不仅仅是最内层循环
// 这在嵌套循环中特别有用,可以避免使用额外的标志变量来控制循环退出
// 标签可以放在任何循环语句前面,不限于最外层循环
// 下面是几种标签使用的示例
// 1. 标签在最外层循环前
outer:
for i := 0; i < 10; i++ {
for j := 0; j < 10; j++ {
if i == 5 && j == 5 {
break outer // 跳出外层循环
}
}
}
// 2. 标签在内层循环前
for i := 0; i < 10; i++ {
inner:
for j := 0; j < 10; j++ {
if j == 5 {
break inner // 跳出内层循环,效果等同于直接break
}
}
}
// 3. 标签也可用于continue语句
loop:
for i := 0; i < 5; i++ {
for j := 0; j < 5; j++ {
if j == 2 {
continue loop // 跳过当前外层循环的迭代,直接进入下一次外层循环
}
}
}
实践练习
1. 基础练习
// 练习1:打印九九乘法表
func main() {
for i := 1; i <= 9; i++ {
for j := 1; j <= i; j++ {
fmt.Printf("%d×%d=%d\t", j, i, i*j)
}
fmt.Println()
}
}
// 练习2:判断素数
func isPrime(n int) bool {
if n <= 1 {
return false
}
for i := 2; i*i <= n; i++ {
if n%i == 0 {
return false
}
}
return true
}
2. 进阶练习
// 练习1:斐波那契数列
func fibonacci(n int) []int {
if n <= 0 {
return []int{}
}
if n == 1 {
return []int{0}
}
fib := make([]int, n)
fib[0] = 0
fib[1] = 1
for i := 2; i < n; i++ {
fib[i] = fib[i-1] + fib[i-2]
}
return fib
}
// 练习2:冒泡排序
func bubbleSort(arr []int) {
n := len(arr)
for i := 0; i < n-1; i++ {
for j := 0; j < n-i-1; j++ {
if arr[j] > arr[j+1] {
arr[j], arr[j+1] = arr[j+1], arr[j]
}
}
}
}
常见问题
1. if 语句问题
- if 语句中的变量作用域:花括号内 ✓ 正确。if语句中声明的变量只在if语句块内可见,包括else和else if块。
- 条件判断的短路特性:一旦有一个条件满足,就不会在判断后面的条件 表述不够准确 在逻辑运算中,对于OR(||)操作,一旦左侧条件为true,右侧条件不会被评估;对于AND(&&)操作,一旦左侧条件为false,右侧条件不会被评估。这称为短路求值。
- 多条件判断的顺序:从左到右判断 ✓ 正确。Go语言中的条件判断总是从左到右进行评估。
2. switch 语句问题
- case 语句的自动 break ✓ 正确。Go语言中的switch语句默认在每个case执行完后自动break,不需要显式添加break语句。
- fallthrough 的使用:强制执行下一个case,不需要判断下一个case是否成立 ✓ 正确。fallthrough关键字会强制执行下一个case的语句,而不检查其条件是否满足。
- switch 语句的类型限制:不知道这个 Go语言中的switch语句有两种主要形式:表达式switch和类型switch。表达式switch比较值,而类型switch使用类型断言比较类型。switch表达式和case值必须是可比较的类型。此外,Go的switch比其他语言更灵活,case可以是表达式,不限于常量或整数。
3. for 循环问题
- 循环变量的作用域:循环内部 不完全正确 循环变量的作用域取决于声明位置。在for初始化语句中声明的变量(如
for i := 0; i < 10; i++中的i)作用域为整个for循环块;而在循环体内声明的变量作用域仅限于循环体内。 - range 循环的副本问题:不知道这个 在range循环中,迭代变量是每次迭代元素的副本,而不是引用。这意味着修改迭代变量不会影响原始集合。例如,
for i, v := range slice {}中,v是slice[i]的副本,修改v不会改变slice[i]的值。 - 无限循环的退出条件:break 不完全正确 无限循环可以通过多种方式退出:1) break语句;2) return语句(如果在函数内);3) panic;4) goto语句跳转到循环外;5) runtime.Goexit()(终止当前goroutine)。
面试题
-
Go 语言中的 switch 语句有什么特点?有初始化语句,可以多判断条件,自动break ✓ 正确,还可以补充:Go的switch更灵活,case可以是表达式而不仅是常量,支持类型switch,没有表达式的switch等同于switch true。
-
for 循环有哪几种形式?for(;;)for实现while,无限for,range for ✓ 正确。Go中for循环有三种基本形式:1) 完整形式
for init; condition; post {};2) 类似while的形式for condition {};3) 无限循环for {};4) 使用range的形式for index, value := range collection {}。 -
break 和 continue 的区别是什么? 未回答 break用于立即终止当前循环,并开始执行循环后的代码;continue用于跳过当前循环的剩余部分,直接进入下一次循环。
-
range 循环中的变量是值拷贝还是引用?range循环中的变量是值拷贝。每次迭代,range提供的是集合元素的副本,而不是引用。这意味着修改这些变量不会影响原始集合中的值。
// 示例:range循环中的值拷贝 func main() { slice := []int{1, 2, 3, 4, 5} // 错误的修改方式 for _, v := range slice { v *= 2 // 这里修改的是副本,不会影响原始切片 } fmt.Println(slice) // 输出: [1 2 3 4 5] // 正确的修改方式 for i := range slice { slice[i] *= 2 // 通过索引修改原始切片 } fmt.Println(slice) // 输出: [2 4 6 8 10] } -
如何实现带标签的 break? 未回答 Go支持带标签的break,通过在循环前定义标签,然后使用
break 标签名可以跳出多层嵌套循环。例如:
1200

被折叠的 条评论
为什么被折叠?



