# 控制结构
条件语句
if语句
基本if语句
package main
import "fmt"
func main() {
age := 18
if age >= 18 {
fmt.Println("你已经成年了")
}
score := 85
if score >= 90 {
fmt.Println("优秀")
} else if score >= 80 {
fmt.Println("良好")
} else if score >= 60 {
fmt.Println("及格")
} else {
fmt.Println("不及格")
}
}
go run if_basic.go
if语句的初始化
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
// if语句中可以包含初始化语句
rand.Seed(time.Now().UnixNano())
if num := rand.Intn(100); num > 50 {
fmt.Printf("随机数 %d 大于 50\n", num)
} else {
fmt.Printf("随机数 %d 小于等于 50\n", num)
}
// 注意:num变量只在if语句块中有效
// 实际应用:错误处理
if err := someFunction(); err != nil {
fmt.Printf("发生错误: %v\n", err)
} else {
fmt.Println("操作成功")
}
}
func someFunction() error {
// 模拟可能出错的函数
if rand.Intn(2) == 0 {
return fmt.Errorf("模拟错误")
}
return nil
}
go run if_init.go
switch语句
基本switch语句
package main
import "fmt"
func main() {
day := 3
switch day {
case 1:
fmt.Println("星期一")
case 2:
fmt.Println("星期二")
case 3:
fmt.Println("星期三")
case 4:
fmt.Println("星期四")
case 5:
fmt.Println("星期五")
case 6, 7: // 多个值
fmt.Println("周末")
default:
fmt.Println("无效的日期")
}
// 字符串switch
grade := "A"
switch grade {
case "A":
fmt.Println("优秀")
case "B":
fmt.Println("良好")
case "C":
fmt.Println("及格")
case "D", "F":
fmt.Println("不及格")
default:
fmt.Println("无效成绩")
}
}
go run switch_basic.go
switch表达式和fallthrough
package main
import "fmt"
func main() {
score := 85
// switch表达式
switch {
case score >= 90:
fmt.Println("A级")
case score >= 80:
fmt.Println("B级")
case score >= 70:
fmt.Println("C级")
case score >= 60:
fmt.Println("D级")
default:
fmt.Println("F级")
}
// fallthrough关键字
num := 2
fmt.Printf("数字 %d 的特性:\n", num)
switch num {
case 1:
fmt.Println("- 是1")
fallthrough
case 2:
fmt.Println("- 是偶数")
fallthrough
case 3:
fmt.Println("- 是小于4的数")
default:
fmt.Println("- 是其他数")
}
}
go run switch_advanced.go
类型switch
package main
import "fmt"
func main() {
// 类型switch用于判断接口变量的实际类型
var value interface{}
values := []interface{}{42, "hello", 3.14, true, []int{1, 2, 3}}
for i, v := range values {
value = v
fmt.Printf("值 %d: ", i+1)
switch val := value.(type) {
case int:
fmt.Printf("整数: %d\n", val)
case string:
fmt.Printf("字符串: %s\n", val)
case float64:
fmt.Printf("浮点数: %.2f\n", val)
case bool:
fmt.Printf("布尔值: %t\n", val)
case []int:
fmt.Printf("整数切片: %v\n", val)
default:
fmt.Printf("未知类型: %T\n", val)
}
}
}
go run type_switch.go
循环语句
for循环
基本for循环
package main
import "fmt"
func main() {
// 传统的for循环
fmt.Println("1到10的数字:")
for i := 1; i <= 10; i++ {
fmt.Printf("%d ", i)
}
fmt.Println()
// 计算阶乘
n := 5
factorial := 1
for i := 1; i <= n; i++ {
factorial *= i
}
fmt.Printf("%d! = %d\n", n, factorial)
// 倒序循环
fmt.Println("倒数计时:")
for i := 5; i > 0; i-- {
fmt.Printf("%d ", i)
}
fmt.Println("发射!")
}
go run for_basic.go
while风格的for循环
package main
import "fmt"
func main() {
// Go中没有while,但可以用for模拟
count := 0
for count < 5 {
fmt.Printf("计数: %d\n", count)
count++
}
// 无限循环(需要break跳出)
sum := 0
for {
sum++
if sum > 10 {
break
}
if sum%2 == 0 {
continue // 跳过偶数
}
fmt.Printf("奇数: %d\n", sum)
}
fmt.Printf("最终sum值: %d\n", sum)
}
go run for_while.go
range循环
遍历数组和切片
package main
import "fmt"
func main() {
// 遍历数组
numbers := [5]int{10, 20, 30, 40, 50}
fmt.Println("使用索引和值:")
for index, value := range numbers {
fmt.Printf("索引 %d: 值 %d\n", index, value)
}
fmt.Println("\n只使用值:")
for _, value := range numbers {
fmt.Printf("%d ", value)
}
fmt.Println()
fmt.Println("\n只使用索引:")
for index := range numbers {
fmt.Printf("索引 %d\n", index)
}
// 遍历切片
fruits := []string{"苹果", "香蕉", "橙子"}
fmt.Println("\n水果列表:")
for i, fruit := range fruits {
fmt.Printf("%d. %s\n", i+1, fruit)
}
}
go run range_slice.go
遍历字符串和映射
package main
import "fmt"
func main() {
// 遍历字符串(按Unicode字符)
text := "Hello, 世界"
fmt.Println("字符串遍历:")
for index, char := range text {
fmt.Printf("位置 %d: 字符 %c (Unicode: %d)\n", index, char, char)
}
// 遍历映射
scores := map[string]int{
"Alice": 95,
"Bob": 87,
"Charlie": 92,
}
fmt.Println("\n学生成绩:")
for name, score := range scores {
fmt.Printf("%s: %d分\n", name, score)
}
// 只遍历键
fmt.Println("\n学生名单:")
for name := range scores {
fmt.Printf("- %s\n", name)
}
}
go run range_string_map.go
循环控制
break和continue
package main
import "fmt"
func main() {
// break示例:找到第一个偶数
numbers := []int{1, 3, 5, 8, 9, 12, 15}
fmt.Println("寻找第一个偶数:")
for i, num := range numbers {
if num%2 == 0 {
fmt.Printf("找到偶数 %d,位置: %d\n", num, i)
break
}
fmt.Printf("跳过奇数: %d\n", num)
}
// continue示例:只打印偶数
fmt.Println("\n只打印偶数:")
for _, num := range numbers {
if num%2 != 0 {
continue // 跳过奇数
}
fmt.Printf("偶数: %d\n", num)
}
// 嵌套循环中的break和continue
fmt.Println("\n九九乘法表(部分):")
for i := 1; i <= 5; i++ {
for j := 1; j <= 5; j++ {
if i*j > 10 {
break // 跳出内层循环
}
fmt.Printf("%d*%d=%d ", i, j, i*j)
}
fmt.Println()
}
}
go run loop_control.go
标签和goto
package main
import "fmt"
func main() {
// 使用标签控制嵌套循环
fmt.Println("寻找特定组合:")
Outer:
for i := 1; i <= 3; i++ {
for j := 1; j <= 3; j++ {
fmt.Printf("i=%d, j=%d\n", i, j)
if i*j == 4 {
fmt.Println("找到目标组合,退出所有循环")
break Outer // 跳出外层循环
}
}
}
// goto语句(不推荐使用,但在某些情况下有用)
fmt.Println("\ngoto示例:")
counter := 0
Loop:
counter++
fmt.Printf("计数: %d\n", counter)
if counter < 3 {
goto Loop
}
fmt.Println("完成")
}
go run labels_goto.go
函数
函数定义
基本函数
package main
import "fmt"
// 无参数无返回值
func sayHello() {
fmt.Println("Hello, World!")
}
// 有参数无返回值
func greet(name string) {
fmt.Printf("Hello, %s!\n", name)
}
// 有参数有返回值
func add(a, b int) int {
return a + b
}
// 多个参数,多个返回值
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, fmt.Errorf("除数不能为零")
}
return a / b, nil
}
func main() {
sayHello()
greet("Alice")
sum := add(10, 20)
fmt.Printf("10 + 20 = %d\n", sum)
result, err := divide(10, 3)
if err != nil {
fmt.Printf("错误: %v\n", err)
} else {
fmt.Printf("10 / 3 = %.2f\n", result)
}
// 除零测试
_, err = divide(10, 0)
if err != nil {
fmt.Printf("错误: %v\n", err)
}
}
go run func_basic.go
命名返回值
package main
import "fmt"
// 命名返回值
func calculate(a, b int) (sum, product int) {
sum = a + b
product = a * b
return // 裸返回
}
// 命名返回值的好处:可读性更好
func parseFullName(fullName string) (firstName, lastName string) {
// 简单的分割逻辑
parts := []string{"John", "Doe"} // 模拟分割结果
if len(parts) >= 2 {
firstName = parts[0]
lastName = parts[1]
}
return
}
// 可以在函数中修改命名返回值
func processNumber(n int) (result int) {
result = n * 2
if result > 100 {
result = 100 // 限制最大值
}
return
}
func main() {
sum, product := calculate(6, 7)
fmt.Printf("6 + 7 = %d, 6 * 7 = %d\n", sum, product)
first, last := parseFullName("John Doe")
fmt.Printf("名: %s, 姓: %s\n", first, last)
result1 := processNumber(30)
result2 := processNumber(60)
fmt.Printf("处理30: %d, 处理60: %d\n", result1, result2)
}
go run func_named_return.go
函数参数
值传递和指针传递
package main
import "fmt"
// 值传递:传递副本
func modifyValue(x int) {
x = x * 2
fmt.Printf("函数内x的值: %d\n", x)
}
// 指针传递:传递地址
func modifyPointer(x *int) {
*x = *x * 2
fmt.Printf("函数内*x的值: %d\n", *x)
}
// 切片传递(引用类型)
func modifySlice(s []int) {
if len(s) > 0 {
s[0] = 999
}
fmt.Printf("函数内切片: %v\n", s)
}
func main() {
// 值传递示例
num := 10
fmt.Printf("调用前num: %d\n", num)
modifyValue(num)
fmt.Printf("调用后num: %d\n", num) // 值不变
fmt.Println()
// 指针传递示例
num2 := 10
fmt.Printf("调用前num2: %d\n", num2)
modifyPointer(&num2)
fmt.Printf("调用后num2: %d\n", num2) // 值改变
fmt.Println()
// 切片传递示例
slice := []int{1, 2, 3, 4, 5}
fmt.Printf("调用前切片: %v\n", slice)
modifySlice(slice)
fmt.Printf("调用后切片: %v\n", slice) // 第一个元素被修改
}
go run func_params.go
可变参数
package main
import "fmt"
// 可变参数函数
func sum(numbers ...int) int {
total := 0
fmt.Printf("接收到 %d 个参数: %v\n", len(numbers), numbers)
for _, num := range numbers {
total += num
}
return total
}
// 混合参数:固定参数 + 可变参数
func greetAll(greeting string, names ...string) {
for _, name := range names {
fmt.Printf("%s, %s!\n", greeting, name)
}
}
// 传递切片给可变参数
func printNumbers(nums ...int) {
for i, num := range nums {
fmt.Printf("第%d个数: %d\n", i+1, num)
}
}
func main() {
// 调用可变参数函数
result1 := sum()
fmt.Printf("无参数求和: %d\n", result1)
result2 := sum(1, 2, 3)
fmt.Printf("三个数求和: %d\n", result2)
result3 := sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
fmt.Printf("十个数求和: %d\n", result3)
fmt.Println()
// 混合参数
greetAll("Hello", "Alice", "Bob", "Charlie")
fmt.Println()
// 传递切片
numbers := []int{10, 20, 30, 40}
printNumbers(numbers...) // 展开切片
}
go run func_variadic.go
高阶函数
函数作为参数
package main
import "fmt"
// 定义函数类型
type Operation func(int, int) int
// 具体的操作函数
func add(a, b int) int {
return a + b
}
func multiply(a, b int) int {
return a * b
}
func subtract(a, b int) int {
return a - b
}
// 高阶函数:接受函数作为参数
func calculate(a, b int, op Operation) int {
return op(a, b)
}
// 应用函数到切片
func applyToSlice(numbers []int, fn func(int) int) []int {
result := make([]int, len(numbers))
for i, num := range numbers {
result[i] = fn(num)
}
return result
}
// 平方函数
func square(x int) int {
return x * x
}
// 双倍函数
func double(x int) int {
return x * 2
}
func main() {
// 使用函数作为参数
fmt.Printf("10 + 5 = %d\n", calculate(10, 5, add))
fmt.Printf("10 * 5 = %d\n", calculate(10, 5, multiply))
fmt.Printf("10 - 5 = %d\n", calculate(10, 5, subtract))
// 使用匿名函数
result := calculate(10, 5, func(a, b int) int {
return a % b
})
fmt.Printf("10 %% 5 = %d\n", result)
// 应用函数到切片
numbers := []int{1, 2, 3, 4, 5}
fmt.Printf("原始数组: %v\n", numbers)
squared := applyToSlice(numbers, square)
fmt.Printf("平方后: %v\n", squared)
doubled := applyToSlice(numbers, double)
fmt.Printf("双倍后: %v\n", doubled)
}
go run func_higher_order.go
函数作为返回值
package main
import "fmt"
// 返回函数的函数
func makeAdder(x int) func(int) int {
return func(y int) int {
return x + y
}
}
// 创建乘法器
func makeMultiplier(factor int) func(int) int {
return func(n int) int {
return n * factor
}
}
// 创建验证器
func makeValidator(min, max int) func(int) bool {
return func(value int) bool {
return value >= min && value <= max
}
}
// 创建计数器(闭包示例)
func makeCounter() func() int {
count := 0
return func() int {
count++
return count
}
}
func main() {
// 使用加法器
add10 := makeAdder(10)
fmt.Printf("add10(5) = %d\n", add10(5))
fmt.Printf("add10(15) = %d\n", add10(15))
add100 := makeAdder(100)
fmt.Printf("add100(5) = %d\n", add100(5))
// 使用乘法器
double := makeMultiplier(2)
triple := makeMultiplier(3)
fmt.Printf("double(7) = %d\n", double(7))
fmt.Printf("triple(7) = %d\n", triple(7))
// 使用验证器
ageValidator := makeValidator(18, 65)
fmt.Printf("年龄25有效: %t\n", ageValidator(25))
fmt.Printf("年龄15有效: %t\n", ageValidator(15))
// 使用计数器(闭包)
counter1 := makeCounter()
counter2 := makeCounter()
fmt.Printf("counter1: %d\n", counter1())
fmt.Printf("counter1: %d\n", counter1())
fmt.Printf("counter2: %d\n", counter2())
fmt.Printf("counter1: %d\n", counter1())
}
go run func_closure.go
递归函数
经典递归示例
package main
import "fmt"
// 阶乘函数
func factorial(n int) int {
if n <= 1 {
return 1
}
return n * factorial(n-1)
}
// 斐波那契数列
func fibonacci(n int) int {
if n <= 1 {
return n
}
return fibonacci(n-1) + fibonacci(n-2)
}
// 优化的斐波那契(使用记忆化)
func fibonacciMemo(n int, memo map[int]int) int {
if n <= 1 {
return n
}
if val, exists := memo[n]; exists {
return val
}
memo[n] = fibonacciMemo(n-1, memo) + fibonacciMemo(n-2, memo)
return memo[n]
}
// 计算最大公约数(欧几里得算法)
func gcd(a, b int) int {
if b == 0 {
return a
}
return gcd(b, a%b)
}
// 二分查找(递归版本)
func binarySearch(arr []int, target, left, right int) int {
if left > right {
return -1 // 未找到
}
mid := left + (right-left)/2
if arr[mid] == target {
return mid
} else if arr[mid] > target {
return binarySearch(arr, target, left, mid-1)
} else {
return binarySearch(arr, target, mid+1, right)
}
}
func main() {
// 阶乘测试
fmt.Println("阶乘计算:")
for i := 0; i <= 6; i++ {
fmt.Printf("%d! = %d\n", i, factorial(i))
}
// 斐波那契测试
fmt.Println("\n斐波那契数列:")
for i := 0; i <= 10; i++ {
fmt.Printf("fib(%d) = %d\n", i, fibonacci(i))
}
// 优化的斐波那契
fmt.Println("\n优化的斐波那契:")
memo := make(map[int]int)
for i := 0; i <= 20; i++ {
fmt.Printf("fib(%d) = %d\n", i, fibonacciMemo(i, memo))
}
// 最大公约数
fmt.Println("\n最大公约数:")
fmt.Printf("gcd(48, 18) = %d\n", gcd(48, 18))
fmt.Printf("gcd(100, 25) = %d\n", gcd(100, 25))
// 二分查找
fmt.Println("\n二分查找:")
arr := []int{1, 3, 5, 7, 9, 11, 13, 15, 17, 19}
target := 7
index := binarySearch(arr, target, 0, len(arr)-1)
if index != -1 {
fmt.Printf("在数组 %v 中找到 %d,位置: %d\n", arr, target, index)
} else {
fmt.Printf("在数组中未找到 %d\n", target)
}
}
go run func_recursive.go
匿名函数和闭包
匿名函数的使用
package main
import (
"fmt"
"sort"
)
func main() {
// 立即执行的匿名函数
result := func(a, b int) int {
return a + b
}(10, 20)
fmt.Printf("立即执行结果: %d\n", result)
// 将匿名函数赋值给变量
multiply := func(x, y int) int {
return x * y
}
fmt.Printf("5 * 6 = %d\n", multiply(5, 6))
// 在切片中使用匿名函数
operations := []func(int, int) int{
func(a, b int) int { return a + b },
func(a, b int) int { return a - b },
func(a, b int) int { return a * b },
func(a, b int) int { return a / b },
}
operationNames := []string{"加法", "减法", "乘法", "除法"}
a, b := 20, 4
for i, op := range operations {
result := op(a, b)
fmt.Printf("%s: %d\n", operationNames[i], result)
}
// 使用匿名函数进行排序
people := []struct {
Name string
Age int
}{
{"Alice", 25},
{"Bob", 30},
{"Charlie", 20},
{"David", 35},
}
fmt.Printf("\n排序前: %v\n", people)
// 按年龄排序
sort.Slice(people, func(i, j int) bool {
return people[i].Age < people[j].Age
})
fmt.Printf("按年龄排序后: %v\n", people)
// 按姓名排序
sort.Slice(people, func(i, j int) bool {
return people[i].Name < people[j].Name
})
fmt.Printf("按姓名排序后: %v\n", people)
}
go run func_anonymous.go
闭包的高级应用
package main
import "fmt"
// 创建累加器
func makeAccumulator(initial int) func(int) int {
sum := initial
return func(value int) int {
sum += value
return sum
}
}
// 创建过滤器
func makeFilter(predicate func(int) bool) func([]int) []int {
return func(numbers []int) []int {
var result []int
for _, num := range numbers {
if predicate(num) {
result = append(result, num)
}
}
return result
}
}
// 创建缓存函数
func memoize(fn func(int) int) func(int) int {
cache := make(map[int]int)
return func(n int) int {
if val, exists := cache[n]; exists {
fmt.Printf("从缓存获取 f(%d) = %d\n", n, val)
return val
}
result := fn(n)
cache[n] = result
fmt.Printf("计算并缓存 f(%d) = %d\n", n, result)
return result
}
}
// 昂贵的计算函数
func expensiveFunction(n int) int {
// 模拟复杂计算
result := 0
for i := 0; i <= n; i++ {
result += i * i
}
return result
}
func main() {
// 累加器示例
fmt.Println("累加器示例:")
acc1 := makeAccumulator(0)
acc2 := makeAccumulator(100)
fmt.Printf("acc1(10) = %d\n", acc1(10))
fmt.Printf("acc1(5) = %d\n", acc1(5))
fmt.Printf("acc2(10) = %d\n", acc2(10))
fmt.Printf("acc1(3) = %d\n", acc1(3))
// 过滤器示例
fmt.Println("\n过滤器示例:")
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
evenFilter := makeFilter(func(n int) bool { return n%2 == 0 })
oddFilter := makeFilter(func(n int) bool { return n%2 != 0 })
bigFilter := makeFilter(func(n int) bool { return n > 5 })
fmt.Printf("原数组: %v\n", numbers)
fmt.Printf("偶数: %v\n", evenFilter(numbers))
fmt.Printf("奇数: %v\n", oddFilter(numbers))
fmt.Printf("大于5: %v\n", bigFilter(numbers))
// 缓存函数示例
fmt.Println("\n缓存函数示例:")
cachedFn := memoize(expensiveFunction)
// 第一次调用,需要计算
cachedFn(5)
// 第二次调用,从缓存获取
cachedFn(5)
// 新的参数,需要计算
cachedFn(3)
// 再次调用,从缓存获取
cachedFn(3)
}
go run func_closure_advanced.go
defer语句
defer基础
defer的基本使用
package main
import "fmt"
func deferExample() {
fmt.Println("函数开始")
defer fmt.Println("defer 1: 这是第一个defer")
defer fmt.Println("defer 2: 这是第二个defer")
defer fmt.Println("defer 3: 这是第三个defer")
fmt.Println("函数中间")
fmt.Println("函数即将结束")
}
// defer在循环中的行为
func deferInLoop() {
fmt.Println("\ndefer在循环中:")
for i := 0; i < 3; i++ {
defer fmt.Printf("defer: i = %d\n", i)
}
fmt.Println("循环结束")
}
// defer的参数求值时机
func deferParameterEvaluation() {
fmt.Println("\ndefer参数求值时机:")
x := 10
defer fmt.Printf("defer中的x: %d\n", x) // x在这里被求值
x = 20
fmt.Printf("修改后的x: %d\n", x)
}
func main() {
deferExample()
deferInLoop()
deferParameterEvaluation()
}
go run defer_basic.go
defer的实际应用
package main
import (
"fmt"
"os"
)
// 文件操作中使用defer
func writeToFile(filename, content string) error {
file, err := os.Create(filename)
if err != nil {
return err
}
defer file.Close() // 确保文件被关闭
_, err = file.WriteString(content)
return err
}
// 资源清理
func processData() {
fmt.Println("开始处理数据")
// 模拟获取资源
defer fmt.Println("清理资源1")
defer fmt.Println("清理资源2")
defer fmt.Println("清理资源3")
fmt.Println("处理数据中...")
// 模拟可能的错误
if true {
fmt.Println("处理完成")
return
}
fmt.Println("这行不会执行")
}
// 性能计时
func measureTime(name string) func() {
fmt.Printf("开始执行 %s\n", name)
return func() {
fmt.Printf("%s 执行完成\n", name)
}
}
func expensiveOperation() {
defer measureTime("昂贵操作")()
// 模拟耗时操作
sum := 0
for i := 0; i < 1000000; i++ {
sum += i
}
fmt.Printf("计算结果: %d\n", sum)
}
func main() {
// 文件操作示例
err := writeToFile("test.txt", "Hello, defer!")
if err != nil {
fmt.Printf("写文件错误: %v\n", err)
} else {
fmt.Println("文件写入成功")
}
// 资源清理示例
processData()
// 性能计时示例
expensiveOperation()
// 清理测试文件
defer os.Remove("test.txt")
}
go run defer_practical.go
恭喜!你已经掌握了Go语言的控制结构。接下来让我们学习Go语言的数据结构,包括数组、切片、映射和结构体。