/* 03-for-loops.go - Go 语言 for 循环详解 学习目标: 1. 掌握 for 循环的各种形式 2. 理解 break 和 continue 的使用 3. 学会使用标签控制嵌套循环 4. 了解无限循环的写法 5. 掌握循环的实际应用场景 知识点: - 传统 for 循环 - while 风格的 for 循环 - 无限循环 - break 和 continue - 标签 (label) - 嵌套循环 - 循环优化技巧 */ package main import ( "fmt" "math/rand" "time" ) func main() { fmt.Println("=== Go 语言 for 循环详解 ===\n") // 演示传统 for 循环 demonstrateTraditionalFor() // 演示 while 风格的 for 循环 demonstrateWhileStyleFor() // 演示无限循环 demonstrateInfiniteLoop() // 演示 break 和 continue demonstrateBreakContinue() // 演示嵌套循环和标签 demonstrateNestedLoopsAndLabels() // 演示循环的实际应用 demonstratePracticalExamples() // 演示循环优化技巧 demonstrateOptimizationTips() } // demonstrateTraditionalFor 演示传统 for 循环 func demonstrateTraditionalFor() { fmt.Println("1. 传统 for 循环:") // 基本的 for 循环 fmt.Printf(" 基本 for 循环 (0-4):\n") for i := 0; i < 5; i++ { fmt.Printf(" i = %d\n", i) } // 倒序循环 fmt.Printf(" 倒序循环 (5-1):\n") for i := 5; i > 0; i-- { fmt.Printf(" i = %d\n", i) } // 步长为 2 的循环 fmt.Printf(" 步长为 2 的循环:\n") for i := 0; i <= 10; i += 2 { fmt.Printf(" i = %d\n", i) } // 多个变量的循环 fmt.Printf(" 多变量循环:\n") for i, j := 0, 10; i < j; i, j = i+1, j-1 { fmt.Printf(" i = %d, j = %d\n", i, j) } // 计算累加和 sum := 0 for i := 1; i <= 10; i++ { sum += i } fmt.Printf(" 1到10的累加和: %d\n", sum) // 计算阶乘 factorial := 1 n := 5 for i := 1; i <= n; i++ { factorial *= i } fmt.Printf(" %d的阶乘: %d\n", n, factorial) fmt.Println() } // demonstrateWhileStyleFor 演示 while 风格的 for 循环 func demonstrateWhileStyleFor() { fmt.Println("2. while 风格的 for 循环:") fmt.Printf(" Go 没有 while 关键字,使用 for 代替\n") // 模拟 while 循环 fmt.Printf(" 模拟 while 循环:\n") count := 0 for count < 5 { fmt.Printf(" count = %d\n", count) count++ } // 条件判断循环 fmt.Printf(" 条件判断循环 (猜数字):\n") target := 7 guess := 1 attempts := 0 for guess != target { attempts++ fmt.Printf(" 第 %d 次猜测: %d", attempts, guess) if guess < target { fmt.Printf(" (太小了)\n") guess += 2 } else { fmt.Printf(" (太大了)\n") guess-- } } fmt.Printf(" 恭喜!第 %d 次猜中了: %d\n", attempts+1, guess) // 读取用户输入直到满足条件 fmt.Printf(" 模拟输入验证:\n") password := "" attempts = 0 correctPassword := "123456" // 模拟用户输入 inputs := []string{"111", "222", "123456"} for password != correctPassword && attempts < 3 { password = inputs[attempts] // 模拟用户输入 attempts++ fmt.Printf(" 第 %d 次输入密码: %s", attempts, password) if password == correctPassword { fmt.Printf(" (正确)\n") } else { fmt.Printf(" (错误)\n") } } if password == correctPassword { fmt.Printf(" 登录成功!\n") } else { fmt.Printf(" 登录失败,超过最大尝试次数\n") } fmt.Println() } // demonstrateInfiniteLoop 演示无限循环 func demonstrateInfiniteLoop() { fmt.Println("3. 无限循环:") fmt.Printf(" 无限循环的写法: for { ... }\n") fmt.Printf(" 通常配合 break 使用\n") // 无限循环示例1: 服务器主循环模拟 fmt.Printf(" 示例1 - 服务器主循环模拟:\n") requestCount := 0 for { requestCount++ fmt.Printf(" 处理第 %d 个请求\n", requestCount) // 模拟处理请求 if requestCount >= 3 { fmt.Printf(" 服务器关闭\n") break } } // 无限循环示例2: 菜单系统 fmt.Printf(" 示例2 - 菜单系统模拟:\n") menuOptions := []string{"查看余额", "转账", "退出"} choice := 0 for { fmt.Printf(" 请选择操作:\n") for i, option := range menuOptions { fmt.Printf(" %d. %s\n", i+1, option) } // 模拟用户选择 choice = (choice % 3) + 1 fmt.Printf(" 用户选择: %d\n", choice) switch choice { case 1: fmt.Printf(" 当前余额: 1000元\n") case 2: fmt.Printf(" 转账功能暂未开放\n") case 3: fmt.Printf(" 谢谢使用,再见!\n") return // 或者使用 break } // 为了演示,只循环一次 break } fmt.Println() } // demonstrateBreakContinue 演示 break 和 continue func demonstrateBreakContinue() { fmt.Println("4. break 和 continue:") // break 示例 fmt.Printf(" break - 跳出循环:\n") for i := 0; i < 10; i++ { if i == 5 { fmt.Printf(" 遇到 %d,跳出循环\n", i) break } fmt.Printf(" i = %d\n", i) } // continue 示例 fmt.Printf(" continue - 跳过当前迭代:\n") for i := 0; i < 10; i++ { if i%2 == 0 { continue // 跳过偶数 } fmt.Printf(" 奇数: %d\n", i) } // 实际应用:处理数据时跳过无效值 fmt.Printf(" 实际应用 - 处理数据跳过无效值:\n") data := []int{1, -2, 3, 0, 5, -6, 7, 8, 0, 9} sum := 0 validCount := 0 for i, value := range data { if value <= 0 { fmt.Printf(" 跳过无效值 data[%d] = %d\n", i, value) continue } sum += value validCount++ fmt.Printf(" 处理有效值 data[%d] = %d\n", i, value) } fmt.Printf(" 有效数据个数: %d,总和: %d,平均值: %.2f\n", validCount, sum, float64(sum)/float64(validCount)) // 查找第一个满足条件的元素 fmt.Printf(" 查找第一个大于 50 的数:\n") numbers := []int{10, 25, 30, 55, 60, 75} found := false for i, num := range numbers { fmt.Printf(" 检查 numbers[%d] = %d\n", i, num) if num > 50 { fmt.Printf(" 找到第一个大于 50 的数: %d\n", num) found = true break } } if !found { fmt.Printf(" 没有找到大于 50 的数\n") } fmt.Println() } // demonstrateNestedLoopsAndLabels 演示嵌套循环和标签 func demonstrateNestedLoopsAndLabels() { fmt.Println("5. 嵌套循环和标签:") // 基本嵌套循环 fmt.Printf(" 基本嵌套循环 - 乘法表:\n") for i := 1; i <= 3; i++ { for j := 1; j <= 3; j++ { fmt.Printf(" %d × %d = %d\n", i, j, i*j) } } // 使用标签控制嵌套循环 fmt.Printf(" 使用标签控制嵌套循环:\n") outer: for i := 1; i <= 3; i++ { for j := 1; j <= 3; j++ { fmt.Printf(" i=%d, j=%d\n", i, j) if i == 2 && j == 2 { fmt.Printf(" 在 i=2, j=2 时跳出外层循环\n") break outer } } } // 标签 continue 示例 fmt.Printf(" 标签 continue 示例:\n") outerContinue: for i := 1; i <= 3; i++ { fmt.Printf(" 外层循环 i = %d\n", i) for j := 1; j <= 3; j++ { if i == 2 && j == 2 { fmt.Printf(" 在 i=2, j=2 时跳过外层循环的当前迭代\n") continue outerContinue } fmt.Printf(" 内层循环 j = %d\n", j) } fmt.Printf(" 外层循环 i = %d 结束\n", i) } // 矩阵搜索示例 fmt.Printf(" 矩阵搜索示例:\n") matrix := [][]int{ {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, } target := 5 found := false search: for i := 0; i < len(matrix); i++ { for j := 0; j < len(matrix[i]); j++ { fmt.Printf(" 检查 matrix[%d][%d] = %d\n", i, j, matrix[i][j]) if matrix[i][j] == target { fmt.Printf(" 找到目标值 %d 在位置 [%d][%d]\n", target, i, j) found = true break search } } } if !found { fmt.Printf(" 未找到目标值 %d\n", target) } fmt.Println() } // demonstratePracticalExamples 演示循环的实际应用 func demonstratePracticalExamples() { fmt.Println("6. 循环的实际应用:") // 示例1: 数组/切片处理 fmt.Printf(" 示例1 - 数组处理:\n") scores := []int{85, 92, 78, 96, 88, 73, 91} // 计算平均分 total := 0 for _, score := range scores { total += score } average := float64(total) / float64(len(scores)) fmt.Printf(" 平均分: %.2f\n", average) // 找出最高分和最低分 maxScore, minScore := scores[0], scores[0] for _, score := range scores { if score > maxScore { maxScore = score } if score < minScore { minScore = score } } fmt.Printf(" 最高分: %d,最低分: %d\n", maxScore, minScore) // 统计及格人数 passCount := 0 for _, score := range scores { if score >= 80 { passCount++ } } fmt.Printf(" 及格人数: %d/%d\n", passCount, len(scores)) // 示例2: 字符串处理 fmt.Printf(" 示例2 - 字符串处理:\n") text := "Hello, 世界! 123" // 统计字符类型 letters, digits, others := 0, 0, 0 for _, char := range text { switch { case (char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z') || char > 127: letters++ case char >= '0' && char <= '9': digits++ default: others++ } } fmt.Printf(" 字符串: \"%s\"\n", text) fmt.Printf(" 字母: %d,数字: %d,其他: %d\n", letters, digits, others) // 示例3: 数学计算 fmt.Printf(" 示例3 - 数学计算 (斐波那契数列):\n") n := 10 fmt.Printf(" 前 %d 个斐波那契数:\n", n) a, b := 0, 1 for i := 0; i < n; i++ { fmt.Printf(" F(%d) = %d\n", i, a) a, b = b, a+b } // 示例4: 模拟游戏 fmt.Printf(" 示例4 - 简单猜数字游戏:\n") rand.Seed(time.Now().UnixNano()) secretNumber := rand.Intn(10) + 1 maxAttempts := 3 // 模拟玩家猜测 guesses := []int{5, 8, secretNumber} for attempt := 1; attempt <= maxAttempts; attempt++ { guess := guesses[attempt-1] // 模拟用户输入 fmt.Printf(" 第 %d 次猜测: %d", attempt, guess) if guess == secretNumber { fmt.Printf(" - 恭喜你猜对了!\n") break } else if guess < secretNumber { fmt.Printf(" - 太小了\n") } else { fmt.Printf(" - 太大了\n") } if attempt == maxAttempts { fmt.Printf(" 游戏结束!正确答案是: %d\n", secretNumber) } } // 示例5: 数据验证 fmt.Printf(" 示例5 - 批量数据验证:\n") emails := []string{ "user@example.com", "invalid-email", "test@domain.org", "@invalid.com", "valid@test.net", } validEmails := 0 for i, email := range emails { isValid := validateEmail(email) fmt.Printf(" 邮箱 %d: %-20s - ", i+1, email) if isValid { fmt.Printf("有效\n") validEmails++ } else { fmt.Printf("无效\n") } } fmt.Printf(" 有效邮箱数量: %d/%d\n", validEmails, len(emails)) fmt.Println() } // demonstrateOptimizationTips 演示循环优化技巧 func demonstrateOptimizationTips() { fmt.Println("7. 循环优化技巧:") // 技巧1: 减少重复计算 fmt.Printf(" 技巧1 - 减少重复计算:\n") data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} // 不好的写法:每次都计算 len(data) fmt.Printf(" 不推荐的写法 (每次计算长度):\n") for i := 0; i < len(data); i++ { // len(data) 在每次迭代时都会被调用 fmt.Printf(" data[%d] = %d\n", i, data[i]) if i >= 2 { // 为了演示,只显示前几个 break } } // 好的写法:预先计算长度 fmt.Printf(" 推荐的写法 (预先计算长度):\n") length := len(data) for i := 0; i < length; i++ { fmt.Printf(" data[%d] = %d\n", i, data[i]) if i >= 2 { break } } // 技巧2: 使用 range 遍历 fmt.Printf(" 技巧2 - 使用 range 遍历 (更简洁):\n") for i, value := range data { fmt.Printf(" data[%d] = %d\n", i, value) if i >= 2 { break } } // 技巧3: 提前退出 fmt.Printf(" 技巧3 - 提前退出优化:\n") numbers := []int{2, 4, 6, 7, 8, 10, 12} // 查找第一个奇数 for i, num := range numbers { fmt.Printf(" 检查 numbers[%d] = %d", i, num) if num%2 == 1 { fmt.Printf(" - 找到第一个奇数: %d\n", num) break // 找到后立即退出,不继续遍历 } fmt.Printf(" - 偶数,继续查找\n") } // 技巧4: 批量处理 fmt.Printf(" 技巧4 - 批量处理:\n") largeData := make([]int, 20) for i := range largeData { largeData[i] = i + 1 } batchSize := 5 fmt.Printf(" 批量处理数据 (批次大小: %d):\n", batchSize) for i := 0; i < len(largeData); i += batchSize { end := i + batchSize if end > len(largeData) { end = len(largeData) } batch := largeData[i:end] fmt.Printf(" 处理批次 %d-%d: %v\n", i, end-1, batch) // 模拟批量处理 batchSum := 0 for _, value := range batch { batchSum += value } fmt.Printf(" 批次总和: %d\n", batchSum) } // 技巧5: 避免不必要的操作 fmt.Printf(" 技巧5 - 避免不必要的操作:\n") matrix2 := [][]int{ {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, } // 只处理对角线元素 fmt.Printf(" 只处理矩阵对角线元素:\n") for i := 0; i < len(matrix2) && i < len(matrix2[0]); i++ { fmt.Printf(" 对角线元素 [%d][%d] = %d\n", i, i, matrix2[i][i]) } fmt.Println() } // 辅助函数 func validateEmail(email string) bool { // 简单的邮箱验证(实际应用中应该使用正则表达式) if len(email) < 5 { return false } hasAt := false hasDot := false atPos := -1 for i, char := range email { if char == '@' { if hasAt || i == 0 || i == len(email)-1 { return false } hasAt = true atPos = i } else if char == '.' && hasAt && i > atPos+1 && i < len(email)-1 { hasDot = true } } return hasAt && hasDot } /* 运行这个程序: go run 03-for-loops.go 学习要点: 1. Go 只有 for 循环,没有 while 和 do-while 2. for 循环有三种形式:传统形式、while 形式、无限循环形式 3. break 用于跳出循环,continue 用于跳过当前迭代 4. 标签可以用来控制嵌套循环的跳转 5. range 关键字提供了遍历数组、切片、字符串等的便捷方式 for 循环的三种形式: 1. for init; condition; post { ... } // 传统形式 2. for condition { ... } // while 形式 3. for { ... } // 无限循环 循环控制: 1. break: 跳出当前循环 2. continue: 跳过当前迭代,继续下一次迭代 3. 标签: 可以跳出或跳过指定的外层循环 优化建议: 1. 减少循环内的重复计算 2. 使用 range 遍历集合类型 3. 适当使用 break 提前退出 4. 考虑批量处理大量数据 5. 避免不必要的嵌套循环 常见应用场景: 1. 数组/切片遍历和处理 2. 数值计算(累加、阶乘等) 3. 字符串处理 4. 数据验证和过滤 5. 算法实现 6. 游戏循环 7. 服务器主循环 注意事项: 1. 避免无限循环(除非有明确的退出条件) 2. 注意循环变量的作用域 3. 在嵌套循环中正确使用标签 4. 考虑循环的时间复杂度 5. 合理使用 break 和 continue */