This commit is contained in:
2026-03-13 23:54:07 +08:00
parent 9c065bcae4
commit d0f8c44411
45 changed files with 3439 additions and 1 deletions
+66
View File
@@ -0,0 +1,66 @@
# 01-if-else - 条件判断
## 知识点讲解
### if语句基本语法
```go
if condition {
// 当condition为true时执行
}
```
### if-else语句
```go
if condition {
// 当condition为true时执行
} else {
// 当condition为false时执行
}
```
### if-else if-else链
```go
if condition1 {
// condition1为true时执行
} else if condition2 {
// condition1为false且condition2为true时执行
} else {
// 所有条件都为false时执行
}
```
### 带初始化语句的if
```go
if err := doSomething(); err != nil {
// 处理错误
}
```
### 逻辑运算符
- `&&` - 逻辑与(AND)
- `||` - 逻辑或(OR)
- `!` - 逻辑非(NOT)
### 重要提示
- 条件表达式必须是布尔值
- Go没有三元运算符,需要使用完整的if-else
- if语句后的`{`必须与if在同一行
- 条件表达式中可以声明变量(作用域仅限if块内)
## 学习目标
完成本练习后,你将:
- ✅ 掌握if语句的基本用法
- ✅ 理解if-else if-else链
- ✅ 能够使用带初始化语句的if
- ✅ 掌握复杂的条件表达式
## 练习说明
打开 `main.go`,根据注释提示填充代码,完成后运行 `go test -v` 验证答案。
+121
View File
@@ -0,0 +1,121 @@
package main
import (
"fmt"
"strconv"
"strings"
)
func exercise1() {
fmt.Println("=== 练习1:简单if判断 ===")
age := 18
// 使用if语句,判断age是否大于等于18
// 如果是,输出"你已经成年了"
if ____ {
fmt.Println("你已经成年了")
} else {
fmt.Println("你还未成年")
}
}
func exercise2() {
fmt.Println("\n=== 练习2:if-else if-else链 ===")
score := 85
// 使用if-else if-else链,根据score判断等级
// 90-100: 优秀
// 80-89: 良好
// 60-79: 及格
// 0-59: 不及格
if ____ {
fmt.Printf("分数: %d, 等级: 优秀\n", score)
} else if ____ {
fmt.Printf("分数: %d, 等级: 良好\n", score)
} else if ____ {
fmt.Printf("分数: %d, 等级: 及格\n", score)
} else {
fmt.Printf("分数: %d, 等级: 不及格\n", score)
}
}
func exercise3() string {
fmt.Println("\n=== 练习3:带初始化语句的if ===")
// 使用带初始化语句的if,将字符串"42"转换为整数
// 如果转换成功,返回字符串"转换成功: 转换后的值"
// 如果转换失败,返回字符串"转换失败"
if num, err := strconv.____; ____ {
return fmt.Sprintf("转换成功: %d", num)
} else {
return "转换失败"
}
}
func exercise4() string {
fmt.Println("\n=== 练习4:复杂条件表达式 ===")
username := "admin"
password := "123456"
isActive := true
// 使用if语句,判断:
// 1. 用户名是"admin"
// 2. 密码是"123456"
// 3. 账户是激活状态
// 三个条件都满足时,返回"登录成功",否则返回"登录失败"
if ____ && ____ && ____ {
return "登录成功"
} else {
return "登录失败"
}
}
func exercise5() bool {
fmt.Println("\n=== 练习5:逻辑非和或运算 ===")
hasPermission := false
isAdmin := true
// 使用if语句,判断"没有权限但可以是管理员"的情况
// 提示:使用 ! 或 ||
if ____ {
return true
}
return false
}
func exercise6() string {
fmt.Println("\n=== 练习6:字符串判断 ===")
email := "test@example.com"
// 使用if语句判断email是否包含"@"
// 提示:使用strings.Contains函数
if ____ {
return "有效的邮箱地址"
} else {
return "无效的邮箱地址"
}
}
func main() {
fmt.Println("=== if-else 练习 ===\n")
exercise1()
exercise2()
result3 := exercise3()
fmt.Println(result3)
result4 := exercise4()
fmt.Println(result4)
result5 := exercise5()
fmt.Printf("练习5结果: %t\n", result5)
result6 := exercise6()
fmt.Println(result6)
}
@@ -0,0 +1,113 @@
package main
import (
"bytes"
"os"
"strings"
"testing"
)
func captureOutput(f func()) string {
old := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
f()
w.Close()
os.Stdout = old
var buf bytes.Buffer
buf.ReadFrom(r)
return buf.String()
}
func TestExercise1(t *testing.T) {
output := captureOutput(exercise1)
tests := []struct {
name string
expected string
}{
{"成年检查", "你已经成年了"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if !strings.Contains(output, tt.expected) {
t.Errorf("期望输出包含 '%s', 但实际输出: %s", tt.expected, output)
}
})
}
}
func TestExercise2(t *testing.T) {
output := captureOutput(exercise2)
tests := []struct {
name string
expected string
}{
{"良好等级检查", "分数: 85, 等级: 良好"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if !strings.Contains(output, tt.expected) {
t.Errorf("期望输出包含 '%s', 但实际输出: %s", tt.expected, output)
}
})
}
}
func TestExercise3(t *testing.T) {
result := exercise3()
if result != "转换成功: 42" {
t.Errorf("期望结果 '转换成功: 42', 实际结果: %s", result)
}
}
func TestExercise4(t *testing.T) {
result := exercise4()
if result != "登录成功" {
t.Errorf("期望结果 '登录成功', 实际结果: %s", result)
}
}
func TestExercise5(t *testing.T) {
result := exercise5()
if result != true {
t.Errorf("期望结果 true, 实际结果: %t", result)
}
}
func TestExercise6(t *testing.T) {
result := exercise6()
if result != "有效的邮箱地址" {
t.Errorf("期望结果 '有效的邮箱地址', 实际结果: %s", result)
}
}
func TestMainFunction(t *testing.T) {
output := captureOutput(main)
requiredSections := []string{
"=== if-else 练习 ===",
"练习1:简单if判断",
"练习2:if-else if-else链",
"练习3:带初始化语句的if",
"练习4:复杂条件表达式",
"练习5:逻辑非和或运算",
"练习6:字符串判断",
}
for _, section := range requiredSections {
if !strings.Contains(output, section) {
t.Errorf("期望输出包含 '%s'", section)
}
}
}
+79
View File
@@ -0,0 +1,79 @@
# 02-switch - switch语句
## 知识点讲解
### 基本switch语法
```go
switch value {
case value1:
// 当value == value1时执行
case value2:
// 当value == value2时执行
default:
// 当value不等于任何case时执行
}
```
### switch重要特性
1. **自动break**:Go的switch不需要显式break,执行完case后自动跳出
2. **fallthrough**:使用fallthrough关键字继续执行下一个case
3. **多值匹配**:一个case可以匹配多个值
4. **无表达式的switch**:相当于if-else if-else的替代
5. **类型switch**:用于类型断言
### 多值匹配
```go
switch day {
case "Monday", "Tuesday":
fmt.Println("工作日")
}
```
### fallthrough
```go
switch num {
case 1:
fmt.Println("one")
fallthrough // 继续执行case 2
case 2:
fmt.Println("two")
}
```
### 无表达式的switch
```go
switch {
case score >= 90:
fmt.Println("优秀")
case score >= 80:
fmt.Println("良好")
}
```
### 类型switch
```go
switch v := i.(type) {
case int:
fmt.Println("整数")
case string:
fmt.Println("字符串")
}
```
## 学习目标
完成本练习后,你将:
- ✅ 掌握switch语句的基本用法
- ✅ 理解多值匹配和fallthrough
- ✅ 学会使用无表达式的switch
- ✅ 了解类型switch的使用
## 练习说明
打开 `main.go`,根据注释提示填充代码,完成后运行 `go test -v` 验证答案。
+134
View File
@@ -0,0 +1,134 @@
package main
import "fmt"
func exercise1() {
fmt.Println("=== 练习1:基本switch ===")
day := 3
// 使用switch语句,根据day的值输出对应的星期
// 1: 星期一, 2: 星期二, 3: 星期三, 4: 星期四
// 5: 星期五, 6: 星期六, 7: 星期日
// 其他: 无效的天数
switch ____ {
case ____:
fmt.Println("星期一")
case ____:
fmt.Println("星期二")
case ____:
fmt.Println("星期三")
case ____:
fmt.Println("星期四")
case ____:
fmt.Println("星期五")
case ____:
fmt.Println("星期六")
case ____:
fmt.Println("星期日")
default:
fmt.Println("无效的天数")
}
}
func exercise2() {
fmt.Println("\n=== 练习2:多值匹配 ===")
month := 1
// 使用switch语句,根据month的值输出季节
// 使用多值匹配(一个case匹配多个值)
// 3,4,5: 春季
// 6,7,8: 夏季
// 9,10,11: 秋季
// 12,1,2: 冬季
switch ____ {
case ____, ____, ____:
fmt.Println("春季")
case ____, ____, ____:
fmt.Println("夏季")
case ____, ____, ____:
fmt.Println("秋季")
case ____, ____, ____:
fmt.Println("冬季")
default:
fmt.Println("无效的月份")
}
}
func exercise3() {
fmt.Println("\n=== 练习3:无表达式的switch ===")
score := 92
// 使用无表达式的switch,根据score判断等级
// 90-100: 优秀
// 80-89: 良好
// 60-79: 及格
// 0-59: 不及格
switch {
case ____:
fmt.Printf("分数: %d, 等级: 优秀\n", score)
case ____:
fmt.Printf("分数: %d, 等级: 良好\n", score)
case ____:
fmt.Printf("分数: %d, 等级: 及格\n", score)
case ____:
fmt.Printf("分数: %d, 等级: 不及格\n", score)
}
}
func exercise4() {
fmt.Println("\n=== 练习4:fallthrough ===")
num := 1
// 使用switch和fallthrough,当num=1时:
// 输出"one"然后继续执行case 2输出"two"
// 提示:在case 1的末尾添加fallthrough
switch ____ {
case 1:
fmt.Println("one")
____
case 2:
fmt.Println("two")
case 3:
fmt.Println("three")
}
}
func exercise5() string {
fmt.Println("\n=== 练习5:switch返回值 ===")
status := 200
// 使用switch语句,根据HTTP状态码返回对应的描述
// 200: OK
// 404: Not Found
// 500: Internal Server Error
// 其他: Unknown Status
var result string
switch ____ {
case 200:
result = "OK"
case 404:
result = "Not Found"
case 500:
result = "Internal Server Error"
default:
result = "Unknown Status"
}
return result
}
func main() {
fmt.Println("=== switch 练习 ===\n")
exercise1()
exercise2()
exercise3()
exercise4()
result := exercise5()
fmt.Println(result)
}
+126
View File
@@ -0,0 +1,126 @@
package main
import (
"bytes"
"os"
"strings"
"testing"
)
func captureOutput(f func()) string {
old := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
f()
w.Close()
os.Stdout = old
var buf bytes.Buffer
buf.ReadFrom(r)
return buf.String()
}
func TestExercise1(t *testing.T) {
output := captureOutput(exercise1)
tests := []struct {
name string
expected string
}{
{"星期三检查", "星期三"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if !strings.Contains(output, tt.expected) {
t.Errorf("期望输出包含 '%s', 但实际输出: %s", tt.expected, output)
}
})
}
}
func TestExercise2(t *testing.T) {
output := captureOutput(exercise2)
tests := []struct {
name string
expected string
}{
{"春季检查", "春季"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if !strings.Contains(output, tt.expected) {
t.Errorf("期望输出包含 '%s', 但实际输出: %s", tt.expected, output)
}
})
}
}
func TestExercise3(t *testing.T) {
output := captureOutput(exercise3)
tests := []struct {
name string
expected string
}{
{"优秀等级检查", "分数: 92, 等级: 优秀"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if !strings.Contains(output, tt.expected) {
t.Errorf("期望输出包含 '%s', 但实际输出: %s", tt.expected, output)
}
})
}
}
func TestExercise4(t *testing.T) {
output := captureOutput(exercise4)
tests := []struct {
name string
expected string
}{
{"one输出检查", "one"},
{"two输出检查", "two"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if !strings.Contains(output, tt.expected) {
t.Errorf("期望输出包含 '%s', 但实际输出: %s", tt.expected, output)
}
})
}
}
func TestExercise5(t *testing.T) {
result := exercise5()
if result != "OK" {
t.Errorf("期望结果 'OK', 实际结果: %s", result)
}
}
func TestMainFunction(t *testing.T) {
output := captureOutput(main)
requiredSections := []string{
"=== switch 练习 ===",
"练习1:基本switch",
"练习2:多值匹配",
"练习3:无表达式的switch",
"练习4:fallthrough",
}
for _, section := range requiredSections {
if !strings.Contains(output, section) {
t.Errorf("期望输出包含 '%s'", section)
}
}
}
@@ -0,0 +1,96 @@
# 03-for-loop - for循环
## 知识点讲解
Go语言只有一种循环语句:`for`,但它有多种形式。
### 基本for循环(类似C的for)
```go
for init; condition; post {
// 循环体
}
```
**示例**:
```go
for i := 0; i < 10; i++ {
fmt.Println(i)
}
```
### while形式(省略init和post)
```go
for condition {
// 循环体
}
```
**示例**:
```go
i := 0
for i < 10 {
fmt.Println(i)
i++
}
```
### 无限循环
```go
for {
// 循环体,需要break或return才能退出
}
```
**示例**:
```go
for {
fmt.Println("无限循环")
break // 退出循环
}
```
### for-range(遍历数组、切片、map、字符串)
```go
// 遍历切片或数组
for index, value := range slice {
fmt.Printf("索引: %d, 值: %v\n", index, value)
}
// 遍历map
for key, value := range m {
fmt.Printf("键: %v, 值: %v\n", key, value)
}
// 遍历字符串(字符索引和rune)
for index, char := range "你好" {
fmt.Printf("索引: %d, 字符: %c\n", index, char)
}
```
### break和continue
- `break`:跳出整个循环
- `continue`:跳过本次循环,进入下一次循环
### 重要提示
- Go没有while循环,for可以替代while
- 循环变量在每次迭代中会重新声明
- for-range遍历字符串时,index是字节位置,value是rune
- 如果不需要索引或值,可以使用`_`忽略
## 学习目标
完成本练习后,你将:
- ✅ 掌握for循环的几种形式
- ✅ 理解for-range的用法
- ✅ 能够使用break和continue
- ✅ 学会遍历字符串、切片和map
## 练习说明
打开 `main.go`,根据注释提示填充代码,完成后运行 `go test -v` 验证答案。
+104
View File
@@ -0,0 +1,104 @@
package main
import "fmt"
func exercise1() int {
fmt.Println("=== 练习1:基本for循环 ===")
sum := 0
// 使用for循环,计算1到10的和(包括10)
// 初始化: i := 1
// 条件: i <= 10
// 后置: i++
for ____; ____; ____ {
sum += i
}
fmt.Printf("1到10的和: %d\n", sum)
return sum
}
func exercise2() int {
fmt.Println("\n=== 练习2:while形式的for循环 ===")
sum := 0
i := 1
// 使用while形式的for循环,计算1到5的乘积
// 提示:省略初始化和后置语句
for ____ {
sum *= i
i++
}
fmt.Printf("1到5的乘积: %d\n", sum)
return sum
}
func exercise3() []int {
fmt.Println("\n=== 练习3:break和continue ===")
nums := []int{}
// 使用for循环,遍历1到10
// 如果数字能被3整除,跳过(使用continue)
// 如果数字大于8,停止循环(使用break)
i := 1
for i <= 10 {
if ____ {
i++
____
}
if ____ {
____
}
nums = append(nums, i)
i++
}
fmt.Printf("符合条件的数字: %v\n", nums)
return nums
}
func exercise4() string {
fmt.Println("\n=== 练习4:for-range遍历切片 ===")
fruits := []string{"苹果", "香蕉", "橙子"}
result := ""
// 使用for-range遍历切片,格式化输出
// 提示:range会返回索引和值,示例: "0: 苹果"
for ____, ____ := range ____ {
result += fmt.Sprintf("%d: %s ", index, value)
}
fmt.Printf("水果列表: %s\n", result)
return result
}
func exercise5() string {
fmt.Println("\n=== 练习5:for-range遍历map ===")
scores := map[string]int{"张三": 90, "李四": 85, "王五": 95}
result := ""
// 使用for-range遍历map,格式化输出
// 提示:range遍历map时,返回的是键和值
for ____, ____ := range ____ {
result += fmt.Sprintf("%s: %d ", name, score)
}
fmt.Printf("成绩表: %s\n", result)
return result
}
func main() {
fmt.Println("=== for循环 练习 ===\n")
exercise1()
exercise2()
exercise3()
exercise4()
exercise5()
}
@@ -0,0 +1,104 @@
package main
import (
"bytes"
"os"
"strings"
"testing"
)
func captureOutput(f func()) string {
old := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
f()
w.Close()
os.Stdout = old
var buf bytes.Buffer
buf.ReadFrom(r)
return buf.String()
}
func TestExercise1(t *testing.T) {
output := captureOutput(exercise1)
tests := []struct {
name string
expected string
}{
{"求和检查", "1到10的和: 55"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if !strings.Contains(output, tt.expected) {
t.Errorf("期望输出包含 '%s', 但实际输出: %s", tt.expected, output)
}
})
}
}
func TestExercise2(t *testing.T) {
output := captureOutput(exercise2)
tests := []struct {
name string
expected string
}{
{"乘积检查", "1到5的乘积: 120"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if !strings.Contains(output, tt.expected) {
t.Errorf("期望输出包含 '%s', 但实际输出: %s", tt.expected, output)
}
})
}
}
func TestExercise3(t *testing.T) {
result := exercise3()
if len(result) != 6 {
t.Errorf("期望结果长度为6, 实际长度: %d", len(result))
}
}
func TestExercise4(t *testing.T) {
result := exercise4()
if !strings.Contains(result, "0: 苹果") {
t.Errorf("期望包含 '0: 苹果', 实际结果: %s", result)
}
}
func TestExercise5(t *testing.T) {
result := exercise5()
requiredNames := []string{"张三", "李四", "王五"}
for _, name := range requiredNames {
if !strings.Contains(result, name) {
t.Errorf("期望包含 '%s', 实际结果: %s", name, result)
}
}
}
func TestMainFunction(t *testing.T) {
output := captureOutput(main)
requiredSections := []string{
"=== for循环 练习 ===",
"练习1:基本for循环",
"练习2:while形式的for循环",
"练习3:break和continue",
"练习4:for-range遍历切片",
"练习5:for-range遍历map",
}
for _, section := range requiredSections {
if !strings.Contains(output, section) {
t.Errorf("期望输出包含 '%s'", section)
}
}
}
+98
View File
@@ -0,0 +1,98 @@
# 04-defer - defer机制
## 知识点讲解
### defer基本语法
`defer`语句会将函数调用推迟到当前函数返回之前执行。
```go
func example() {
defer fmt.Println("最后执行")
fmt.Println("先执行")
}
// 输出:
// 先执行
// 最后执行
```
### defer的执行顺序
多个defer语句按照**后进先出(LIFO)**的顺序执行。
```go
func example() {
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
}
// 输出:
// 3
// 2
// 1
```
### defer的参数求值
defer语句中的函数参数在defer声明时就被求值(立即求值),而不是在实际执行时。
```go
func example() {
i := 0
defer fmt.Println(i) // i=0 在此时被求值
i = 10
}
// 输出: 0 (而不是10)
```
### defer修改返回值
使用具名返回值时,defer可以修改返回值。
```go
func example() (result int) {
defer func() {
result = 100 // 修改返回值
}()
return 50
}
// 返回: 100
```
### defer的常见用途
1. **关闭资源**:
```go
file, err := os.Open("file.txt")
if err != nil {
return err
}
defer file.Close() // 确保文件被关闭
```
2. **释放锁**:
```go
mutex.Lock()
defer mutex.Unlock() // 确保锁被释放
```
3. **恢复panic**:
```go
defer func() {
if r := recover(); r != nil {
fmt.Println("恢复:", r)
}
}()
```
## 学习目标
完成本练习后,你将:
- ✅ 理解defer的执行时机
- ✅ 掌握defer的执行顺序(LIFO)
- ✅ 了解defer参数的立即求值特性
- ✅ 学会defer的常见应用场景
## 练习说明
打开 `main.go`,根据注释提示填充代码,完成后运行 `go test -v` 验证答案。
+90
View File
@@ -0,0 +1,90 @@
package main
import "fmt"
func exercise1() {
fmt.Println("=== 练习1:defer基本用法 ===")
// 使用defer,在函数结束时打印"函数结束"
____
fmt.Println("函数执行中")
}
func exercise2() {
fmt.Println("\n=== 练习2:defer执行顺序 ===")
// 使用多个defer语句,按照1-2-3的顺序声明
// 观察输出的顺序(应该是3-2-1)
____
____
____
fmt.Println("正常执行")
}
func exercise3() int {
fmt.Println("\n=== 练习3:defer修改返回值 ===")
// 使用具名返回值result
// defer函数中将result修改为100
// return返回50
var ____ int = ____
defer func() {
____ = ____
}()
return ____
}
func exercise4() {
fmt.Println("\n=== 练习4:defer参数求值 ===")
i := 0
// 使用defer打印i的值
// 注意:defer声明时就对参数求值了
____
i = 10
fmt.Println("修改i为:", i)
}
func exercise5() {
fmt.Println("\n=== 练习5:实际场景 - 模拟资源管理 ===")
// 模拟打开资源
resource := "文件句柄"
fmt.Println("打开:", resource)
// 使用defer在函数结束时关闭资源
defer func() {
fmt.Println("关闭:", ____)
}()
fmt.Println("使用:", resource)
}
func exercise6() {
fmt.Println("\n=== 练习6:defer捕获变量的值 ===")
// 使用循环声明多个defer
// 每个defer捕获当前i的值并打印
// 提示:使用闭包或立即求值
for i := 1; i <= 3; i++ {
____ func(n int) {
fmt.Printf("defer输出: %d\n", n)
}(____)
fmt.Println("循环输出:", i)
}
}
func main() {
fmt.Println("=== defer 练习 ===\n")
exercise1()
exercise2()
fmt.Printf("练习3返回值: %d\n", exercise3())
exercise4()
exercise5()
exercise6()
}
@@ -0,0 +1,97 @@
package main
import (
"bytes"
"os"
"strings"
"testing"
)
func captureOutput(f func()) string {
old := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
f()
w.Close()
os.Stdout = old
var buf bytes.Buffer
buf.ReadFrom(r)
return buf.String()
}
func TestExercise1(t *testing.T) {
output := captureOutput(exercise1)
if !strings.Contains(output, "函数结束") {
t.Error("期望输出包含 '函数结束'")
}
}
func TestExercise2(t *testing.T) {
output := captureOutput(exercise2)
expected := []string{"正常执行", "defer输出: 3", "defer输出: 2", "defer输出: 1"}
for _, exp := range expected {
if !strings.Contains(output, exp) {
t.Errorf("期望输出包含 '%s', 实际: %s", exp, output)
}
}
}
func TestExercise3(t *testing.T) {
result := exercise3()
if result != 100 {
t.Errorf("期望返回值 100, 实际: %d", result)
}
}
func TestExercise4(t *testing.T) {
output := captureOutput(exercise4)
// defer应该在函数结束时打印i的初始值0
if !strings.Contains(output, "defer输出: 0") {
t.Error("期望输出包含 'defer输出: 0'")
}
}
func TestExercise5(t *testing.T) {
output := captureOutput(exercise5)
if !strings.Contains(output, "关闭: 文件句柄") {
t.Error("期望输出包含 '关闭: 文件句柄'")
}
}
func TestExercise6(t *testing.T) {
output := captureOutput(exercise6)
expected := []string{"循环输出: 1", "循环输出: 2", "循环输出: 3"}
for _, exp := range expected {
if !strings.Contains(output, exp) {
t.Errorf("期望输出包含 '%s', 实际: %s", exp, output)
}
}
}
func TestMainFunction(t *testing.T) {
output := captureOutput(main)
requiredSections := []string{
"=== defer 练习 ===",
"练习1:defer基本用法",
"练习2:defer执行顺序",
"练习3:defer修改返回值",
"练习4:defer参数求值",
"练习5:实际场景 - 模拟资源管理",
"练习6:defer捕获变量的值",
}
for _, section := range requiredSections {
if !strings.Contains(output, section) {
t.Errorf("期望输出包含 '%s'", section)
}
}
}
+28
View File
@@ -0,0 +1,28 @@
# Stage 02 - 控制结构
学习Go语言的控制结构,包括条件判断、循环和defer机制。
## 学习目标
完成本阶段后,你将掌握:
- ✅ if/else条件判断
- ✅ switch语句(包括类型switch)
- ✅ for循环的各种形式(Go只有for)
- ✅ defer的执行时机和作用
## 练习列表
1. **01-if-else** - 条件判断
2. **02-switch** - switch语句
3. **03-for-loop** - for循环
4. **04-defer** - defer机制
## 预计用时
每练习15-20分钟,本阶段约1-1.5小时
## 备注
- Go语言没有while循环,for可以替代while
- switch不需要break,但可以使用fallthrough
- defer的执行顺序是LIFO(后进先出)