Go 控制结构
if 语句
基本用法
package main
import "fmt"
func main() {
// 基本 if 语句
x := 10
if x > 5 {
fmt.Println("x 大于 5")
}
// if-else 语句
if x > 15 {
fmt.Println("x 大于 15")
} else {
fmt.Println("x 不大于 15")
}
// if-else if-else 语句
if x > 15 {
fmt.Println("x 大于 15")
} else if x > 10 {
fmt.Println("x 大于 10 但小于等于 15")
} else {
fmt.Println("x 小于等于 10")
}
// if 语句中的短变量声明
// 变量作用域只在 if 语句块内
if y := 20; y > 10 {
fmt.Printf("y (%d) 大于 10\n", y)
}
// fmt.Println(y) // 错误:y 不在作用域内
// 常见用法:错误处理
result, err := divide(10, 2)
if err != nil {
fmt.Printf("错误: %v\n", err)
} else {
fmt.Printf("结果: %d\n", result)
}
// 更简洁的错误处理
if result, err := divide(10, 0); err != nil {
fmt.Printf("错误: %v\n", err)
} else {
fmt.Printf("结果: %d\n", result)
}
}
func divide(a, b int) (int, error) {
if b == 0 {
return 0, fmt.Errorf("除数不能为 0")
}
return a / b, nil
}switch 语句
基本用法
package main
import "fmt"
func main() {
// 基本 switch 语句
day := 3
switch day {
case 1:
fmt.Println("星期一")
case 2:
fmt.Println("星期二")
case 3:
fmt.Println("星期三")
default:
fmt.Println("其他")
}
// switch 语句中的短变量声明
switch num := 5; num {
case 1, 2, 3:
fmt.Println("小数字")
case 4, 5, 6:
fmt.Println("中等数字")
default:
fmt.Println("大数字")
}
// 无表达式的 switch(相当于 if-else if-else)
score := 85
switch {
case score >= 90:
fmt.Println("优秀")
case score >= 80:
fmt.Println("良好")
case score >= 60:
fmt.Println("及格")
default:
fmt.Println("不及格")
}
// fallthrough:继续执行下一个 case
x := 1
switch x {
case 1:
fmt.Println("1")
fallthrough // 继续执行 case 2
case 2:
fmt.Println("2")
case 3:
fmt.Println("3")
}
// 输出:
// 1
// 2
// 类型 switch(用于接口类型)
var i interface{} = "hello"
switch v := i.(type) {
case int:
fmt.Printf("整数: %d\n", v)
case string:
fmt.Printf("字符串: %s\n", v)
case bool:
fmt.Printf("布尔: %t\n", v)
default:
fmt.Printf("未知类型: %T\n", v)
}
}for 循环
基本用法
package main
import "fmt"
func main() {
// 基本 for 循环(类似 C 语言)
for i := 0; i < 5; i++ {
fmt.Printf("%d ", i)
}
fmt.Println() // 输出:0 1 2 3 4
// 只有条件的 for 循环(类似 while)
i := 0
for i < 5 {
fmt.Printf("%d ", i)
i++
}
fmt.Println() // 输出:0 1 2 3 4
// 无限循环
j := 0
for {
if j >= 5 {
break // 跳出循环
}
fmt.Printf("%d ", j)
j++
}
fmt.Println() // 输出:0 1 2 3 4
// continue:跳过本次循环
for i := 0; i < 5; i++ {
if i == 2 {
continue // 跳过 i == 2 的情况
}
fmt.Printf("%d ", i)
}
fmt.Println() // 输出:0 1 3 4
// 嵌套循环和标签
outer:
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
if i == 1 && j == 1 {
break outer // 跳出外层循环
}
fmt.Printf("(%d,%d) ", i, j)
}
}
fmt.Println() // 输出:(0,0) (0,1) (0,2) (1,0)
}range 循环
package main
import "fmt"
func main() {
// 遍历数组/切片
arr := []int{10, 20, 30, 40, 50}
for index, value := range arr {
fmt.Printf("索引 %d: 值 %d\n", index, value)
}
// 只要索引
for index := range arr {
fmt.Printf("索引: %d\n", index)
}
// 只要值(使用 _ 忽略索引)
for _, value := range arr {
fmt.Printf("值: %d\n", value)
}
// 遍历字符串(按 rune)
str := "Hello"
for index, char := range str {
fmt.Printf("索引 %d: 字符 %c (Unicode: %d)\n", index, char, char)
}
// 遍历 map
m := map[string]int{
"apple": 5,
"banana": 3,
"orange": 2,
}
for key, value := range m {
fmt.Printf("键: %s, 值: %d\n", key, value)
}
// 遍历 channel(需要先关闭 channel)
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
close(ch) // 关闭 channel
for value := range ch {
fmt.Printf("从 channel 接收: %d\n", value)
}
}defer 语句
package main
import "fmt"
func main() {
// defer 语句:延迟执行,在函数返回前执行
defer fmt.Println("延迟执行 1")
defer fmt.Println("延迟执行 2")
defer fmt.Println("延迟执行 3")
fmt.Println("正常执行")
// 输出:
// 正常执行
// 延迟执行 3
// 延迟执行 2
// 延迟执行 1
// 注意:defer 执行顺序是 LIFO(后进先出)
// defer 的常见用途:资源清理
deferExample()
}
func deferExample() {
fmt.Println("开始")
// 模拟打开文件
fmt.Println("打开文件")
defer fmt.Println("关闭文件") // 确保文件被关闭
// 模拟处理文件
fmt.Println("处理文件")
// 函数返回时,defer 语句会执行
// 输出:
// 开始
// 打开文件
// 处理文件
// 关闭文件
}
// defer 捕获返回值
func deferReturn() (result int) {
defer func() {
result++ // 修改返回值
}()
return 0 // 实际返回 1
}
// defer 与 panic/recover
func deferPanic() {
defer func() {
if r := recover(); r != nil {
fmt.Printf("捕获到 panic: %v\n", r)
}
}()
panic("发生错误")
fmt.Println("这行不会执行")
}goto 语句
package main
import "fmt"
func main() {
// goto 语句:跳转到标签
i := 0
loop: // 标签
if i < 5 {
fmt.Printf("%d ", i)
i++
goto loop // 跳转到 loop 标签
}
fmt.Println() // 输出:0 1 2 3 4
// goto 的常见用途:错误处理
err := process()
if err != nil {
goto cleanup
}
fmt.Println("处理成功")
cleanup:
fmt.Println("清理资源")
}
func process() error {
// 模拟处理
return nil
}break 和 continue
package main
import "fmt"
func main() {
// break:跳出循环
for i := 0; i < 10; i++ {
if i == 5 {
break // 跳出循环
}
fmt.Printf("%d ", i)
}
fmt.Println() // 输出:0 1 2 3 4
// continue:跳过本次循环
for i := 0; i < 10; i++ {
if i%2 == 0 {
continue // 跳过偶数
}
fmt.Printf("%d ", i)
}
fmt.Println() // 输出:1 3 5 7 9
// 带标签的 break
outer:
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
if i == 1 && j == 1 {
break outer // 跳出外层循环
}
fmt.Printf("(%d,%d) ", i, j)
}
}
fmt.Println()
// 带标签的 continue
outer2:
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
if i == 1 && j == 1 {
continue outer2 // 继续外层循环的下一次迭代
}
fmt.Printf("(%d,%d) ", i, j)
}
}
fmt.Println()
}控制结构最佳实践
package main
import (
"fmt"
"os"
)
func main() {
// 1. 错误处理模式
file, err := os.Open("file.txt")
if err != nil {
fmt.Printf("打开文件失败: %v\n", err)
return
}
defer file.Close() // 确保文件被关闭
// 2. 早期返回模式(减少嵌套)
// 不好的写法(深层嵌套)
func badStyle() {
if condition1 {
if condition2 {
if condition3 {
// 处理逻辑
}
}
}
}
// 好的写法(早期返回)
func goodStyle() {
if !condition1 {
return
}
if !condition2 {
return
}
if !condition3 {
return
}
// 处理逻辑
}
// 3. switch 用于多值判断
value := 5
switch value {
case 1, 2, 3:
fmt.Println("小")
case 4, 5, 6:
fmt.Println("中")
default:
fmt.Println("大")
}
// 4. range 遍历(推荐)
arr := []int{1, 2, 3, 4, 5}
for _, v := range arr {
fmt.Println(v)
}
// 5. defer 用于资源清理
func resourceCleanup() {
// 打开资源
resource := acquireResource()
defer releaseResource(resource) // 确保释放
// 使用资源
useResource(resource)
}
}
func acquireResource() interface{} {
return "resource"
}
func releaseResource(r interface{}) {
fmt.Println("释放资源")
}
func useResource(r interface{}) {
fmt.Println("使用资源")
}总结
Go 的控制结构特点:
- if 语句:支持短变量声明,常用于错误处理
- switch 语句:功能强大,支持类型判断
- for 循环:只有一种循环语句,但用法灵活
- range 循环:遍历数组、切片、map、字符串、channel
- defer 语句:延迟执行,常用于资源清理
- break/continue:支持标签,可以控制外层循环
掌握这些控制结构后,就可以编写复杂的程序逻辑了!