前言

Go(又称Golang)是由Google开发的开源编程语言,自2009年首次发布以来,凭借其简洁性、高性能和出色的并发支持,已成为云原生应用、微服务架构和系统编程的首选语言。截至2026年,Go 1.25版本带来了泛型完善、性能优化和现代化工具链的重大改进。本文将带你全面掌握Go的核心概念、语法特性、最佳实践和高级功能。

第一章:Go概述与核心概念

1.1 什么是Go?

Go是一种静态类型、编译型的编程语言,由Robert Griesemer、Rob Pike和Ken Thompson在Google开发。它结合了C语言的性能、Python的简洁性和现代语言的安全特性。

核心特点

  • 简洁性:语法简单,关键字少(仅25个),学习曲线平缓
  • 高性能:编译为机器码,执行速度快,内存占用低
  • 并发支持:goroutine和channel提供轻量级并发模型
  • 垃圾回收:自动内存管理,减少内存泄漏风险
  • 跨平台:支持Windows、Linux、macOS、ARM等多平台编译
  • 标准库丰富:内置HTTP、JSON、加密、测试等强大功能
  • 快速编译:增量编译,大型项目也能快速构建
  • 工具链完善:go fmt、go vet、go test等内置工具
  • 云原生友好:Docker、Kubernetes等基础设施均用Go编写

1.2 Go版本演进

版本 发布年份 主要特性
Go 1.0 2012 基础语法、goroutine、channel
Go 1.4 2014 自举编译器(Go编写Go编译器)
Go 1.5 2015 并发垃圾回收、vendor支持
Go 1.8 2017 插件支持、HTTP/2服务器推送
Go 1.11 2018 模块支持(go mod)、WebAssembly
Go 1.13 2019 错误包装、数字字面量改进
Go 1.16 2021 嵌入文件、io/fs接口
Go 1.18 2022 泛型支持、工作区模式
Go 1.20 2023 取消context、profile-guided优化
Go 1.22 2024 循环变量捕获修复、range-over-func
Go 1.23 2024 迭代器、切片到数组转换
Go 1.24 2025 异步函数、更好的错误处理
Go 1.25 2026 泛型完善、性能优化、AI工具集成

当前推荐版本:Go 1.25 (2026年)

1.3 Go应用领域

  • Web后端:API服务、微服务、RESTful服务
  • 云原生:Kubernetes、Docker、Prometheus等基础设施
  • DevOps工具:Terraform、Helm、Vault等
  • 命令行工具:高效、单二进制文件分发
  • 数据处理:ETL、批处理、实时流处理
  • 网络编程:TCP/UDP服务器、代理、负载均衡
  • 区块链:以太坊、Cosmos等区块链项目
  • 嵌入式系统:IoT设备、边缘计算

第二章:环境准备与安装

2.1 系统要求

硬件要求

  • CPU:至少1 GHz
  • 内存:至少1 GB(开发环境)
  • 磁盘:至少2 GB可用空间

软件依赖

  • 操作系统:Windows 10+、Linux、macOS 12+
  • Git(用于模块管理)

2.2 安装方法

Windows安装
# 使用winget(推荐)
winget install GoLang.Go

# 使用Chocolatey
choco install golang

# 验证安装
go version
macOS安装
# 使用Homebrew(推荐)
brew install go

# 使用安装包
# 下载 .pkg from https://golang.org/dl/

# 验证安装
go version
Linux安装 (Ubuntu/Debian)
# 使用官方包
wget https://go.dev/dl/go1.25.0.linux-amd64.tar.gz
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.25.0.linux-amd64.tar.gz

# 添加到PATH
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
source ~/.bashrc

# 验证安装
go version

2.3 开发工具

IDE选择
  • Visual Studio Code:配合Go扩展,轻量级且功能强大
  • GoLand:JetBrains出品的专业Go IDE
  • Vim/Neovim:配合vim-go插件
  • Emacs:配合go-mode
项目创建
# 创建新项目
mkdir myproject
cd myproject
go mod init myproject

# 创建main.go
cat > main.go << EOF
package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}
EOF

# 运行项目
go run main.go

# 构建项目
go build

# 安装项目(生成可执行文件到GOPATH/bin)
go install

2.4 第一个Go程序

// main.go
package main

import (
    "fmt"
    "os"
)

func main() {
    // 基本输出
    fmt.Println("Hello, World!")
    
    // 读取命令行参数
    if len(os.Args) > 1 {
        name := os.Args[1]
        fmt.Printf("Hello, %s!\n", name)
    } else {
        fmt.Println("Please provide a name as argument")
    }
}

运行程序

# 初始化模块
go mod init hello

# 运行程序
go run main.go Alice

# 构建可执行文件
go build -o hello main.go
./hello Bob

# 交叉编译
GOOS=linux GOARCH=amd64 go build -o hello-linux main.go
GOOS=windows GOARCH=amd64 go build -o hello.exe main.go

第三章:Go基础语法

3.1 基本语法结构

包和导入
// 文件必须属于某个包
package main // main包用于可执行程序

// 导入标准库
import (
    "fmt"
    "os"
    "strings"
)

// 导入第三方包
import (
    "github.com/gin-gonic/gin"
)

// 点导入(不推荐)
import . "fmt" // 直接使用Println而不是fmt.Println

// 别名导入
import (
    g "github.com/gin-gonic/gin"
    json "encoding/json"
)

// 空导入(仅执行init函数)
import _ "net/http/pprof"
注释和文档
// 单行注释

/*
多行注释
*/

// Package comment describes the package.
package main

// ExportedFunction does something important.
// It takes a parameter and returns a result.
// Example:
//   result := ExportedFunction("input")
//   fmt.Println(result)
func ExportedFunction(param string) string {
    return "processed: " + param
}

// unexportedFunction is not exported (starts with lowercase).
func unexportedFunction() {
    // Internal implementation
}

3.2 变量和数据类型

基本数据类型
package main

import "fmt"

func main() {
    // 整数类型
    var int8Var int8 = 127
    var int16Var int16 = 32767
    var int32Var int32 = 2147483647
    var int64Var int64 = 9223372036854775807
    
    // 无符号整数
    var uint8Var uint8 = 255
    var uint16Var uint16 = 65535
    var uint32Var uint32 = 4294967295
    var uint64Var uint64 = 18446744073709551615
    
    // 浮点类型
    var float32Var float32 = 3.14
    var float64Var float64 = 3.141592653589793
    
    // 复数类型
    var complex64Var complex64 = 1 + 2i
    var complex128Var complex128 = 3 + 4i
    
    // 字符串
    var stringVar string = "Hello, World!"
    var rawString string = `This is a raw string
that spans multiple lines
with "quotes" included.`
    
    // 布尔类型
    var boolVar bool = true
    
    // 字节和符文
    var byteVar byte = 'A' // byte is alias for uint8
    var runeVar rune = '中' // rune is alias for int32
    
    fmt.Println(int8Var, int16Var, int32Var, int64Var)
    fmt.Println(uint8Var, uint16Var, uint32Var, uint64Var)
    fmt.Println(float32Var, float64Var)
    fmt.Println(complex64Var, complex128Var)
    fmt.Println(stringVar, rawString)
    fmt.Println(boolVar)
    fmt.Println(byteVar, runeVar)
}
变量声明和初始化
package main

import "fmt"

func main() {
    // 完整声明
    var name string = "Alice"
    var age int = 25
    var salary float64 = 75000.50
    
    // 类型推断
    var city = "New York" // string
    var population = 8400000 // int
    
    // 短变量声明(仅在函数内使用)
    country := "USA"
    continent := "North America"
    
    // 多变量声明
    var firstName, lastName string = "John", "Doe"
    x, y := 10, 20
    a, b, c := true, 3.14, "hello"
    
    // 批量声明
    var (
        id      int
        status  string
        created bool
    )
    
    // 零值初始化
    var zeroInt int     // 0
    var zeroString string // ""
    var zeroBool bool   // false
    var zeroFloat float64 // 0.0
    
    fmt.Println(name, age, salary)
    fmt.Println(city, population)
    fmt.Println(country, continent)
    fmt.Println(firstName, lastName)
    fmt.Println(x, y, a, b, c)
    fmt.Println(id, status, created)
    fmt.Println(zeroInt, zeroString, zeroBool, zeroFloat)
}
常量
package main

import "fmt"

func main() {
    // 基本常量
    const pi = 3.14159
    const appName = "MyApp"
    const maxRetries = 3
    
    // 显式类型常量
    const timeoutSeconds int = 30
    const debugMode bool = true
    
    // 批量常量
    const (
        StatusPending = "pending"
        StatusActive  = "active"
        StatusClosed  = "closed"
    )
    
    // iota枚举
    const (
        Red = iota // 0
        Green      // 1
        Blue       // 2
    )
    
    const (
        _           = iota // 忽略第一个值
        KB          = 1 << (10 * iota) // 1024
        MB                               // 1048576
        GB                               // 1073741824
        TB                               // 1099511627776
    )
    
    fmt.Println(pi, appName, maxRetries)
    fmt.Println(timeoutSeconds, debugMode)
    fmt.Println(StatusPending, StatusActive, StatusClosed)
    fmt.Println(Red, Green, Blue)
    fmt.Println(KB, MB, GB, TB)
}

3.3 运算符和表达式

算术运算符
package main

import "fmt"

func main() {
    a, b := 10, 3
    
    fmt.Println(a + b) // 13
    fmt.Println(a - b) // 7
    fmt.Println(a * b) // 30
    fmt.Println(a / b) // 3 (整数除法)
    fmt.Println(a % b) // 1 (取余)
    
    // 复合赋值
    x := 5
    x += 3 // x = 8
    x -= 2 // x = 6
    x *= 4 // x = 24
    x /= 3 // x = 8
    x %= 5 // x = 3
    
    fmt.Println(x)
    
    // 递增/递减(Go没有++/--作为表达式)
    y := 10
    y++ // y = 11
    y-- // y = 10
    
    fmt.Println(y)
}
比较和逻辑运算符
package main

import "fmt"

func main() {
    x, y := 5, 10
    
    // 比较运算符
    fmt.Println(x == y) // false
    fmt.Println(x != y) // true
    fmt.Println(x < y)  // true
    fmt.Println(x >= y) // false
    
    // 逻辑运算符
    condition1, condition2 := true, false
    
    fmt.Println(condition1 && condition2) // false
    fmt.Println(condition1 || condition2) // true
    fmt.Println(!condition1)             // false
    
    // 位运算符
    a, b := 12, 10 // 1100, 1010
    
    fmt.Printf("%b & %b = %b\n", a, b, a&b) // 1000 (8)
    fmt.Printf("%b | %b = %b\n", a, b, a|b) // 1110 (14)
    fmt.Printf("%b ^ %b = %b\n", a, b, a^b) // 0110 (6)
    fmt.Printf("~%b = %b\n", a, ^a)         // 取反
    fmt.Printf("%b << 2 = %b\n", a, a<<2)   // 110000 (48)
    fmt.Printf("%b >> 2 = %b\n", a, a>>2)   // 0011 (3)
}

3.4 控制结构

条件语句
package main

import "fmt"

func main() {
    // if语句
    score := 85
    
    if score >= 90 {
        fmt.Println("Grade: A")
    } else if score >= 80 {
        fmt.Println("Grade: B")
    } else if score >= 70 {
        fmt.Println("Grade: C")
    } else {
        fmt.Println("Grade: F")
    }
    
    // if with initialization
    if age := 25; age >= 18 {
        fmt.Println("Adult")
    } else {
        fmt.Println("Minor")
    }
    
    // switch语句
    day := "Monday"
    
    switch day {
    case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday":
        fmt.Println("Weekday")
    case "Saturday", "Sunday":
        fmt.Println("Weekend")
    default:
        fmt.Println("Invalid day")
    }
    
    // switch with initialization
    switch hour := 14; {
    case hour < 12:
        fmt.Println("Morning")
    case hour < 18:
        fmt.Println("Afternoon")
    default:
        fmt.Println("Evening")
    }
    
    // type switch
    var value interface{} = "hello"
    
    switch v := value.(type) {
    case string:
        fmt.Printf("String: %s\n", v)
    case int:
        fmt.Printf("Integer: %d\n", v)
    case bool:
        fmt.Printf("Boolean: %t\n", v)
    default:
        fmt.Println("Unknown type")
    }
}
循环语句
package main

import "fmt"

func main() {
    // for循环(Go只有for,没有while)
    for i := 0; i < 5; i++ {
        fmt.Printf("Iteration %d\n", i)
    }
    
    // while风格循环
    count := 0
    for count < 3 {
        fmt.Printf("Count: %d\n", count)
        count++
    }
    
    // 无限循环
    sum := 0
    for {
        sum++
        if sum >= 10 {
            break
        }
    }
    fmt.Printf("Sum: %d\n", sum)
    
    // range循环(遍历集合)
    fruits := []string{"apple", "banana", "orange"}
    
    // 只获取值
    for _, fruit := range fruits {
        fmt.Println(fruit)
    }
    
    // 获取索引和值
    for index, fruit := range fruits {
        fmt.Printf("Index %d: %s\n", index, fruit)
    }
    
    // 遍历map
    ages := map[string]int{
        "Alice": 25,
        "Bob":   30,
        "Carol": 35,
    }
    
    for name, age := range ages {
        fmt.Printf("%s is %d years old\n", name, age)
    }
    
    // 遍历字符串(按rune)
    text := "Hello 世界"
    for i, char := range text {
        fmt.Printf("Position %d: %c (U+%04X)\n", i, char, char)
    }
    
    // continue和break
    for i := 0; i < 10; i++ {
        if i == 3 {
            continue // 跳过当前迭代
        }
        if i == 7 {
            break // 退出循环
        }
        fmt.Println(i)
    }
    
    // 带标签的break/continue
outer:
    for i := 0; i < 3; i++ {
        for j := 0; j < 3; j++ {
            if i == 1 && j == 1 {
                break outer // 跳出外层循环
            }
            fmt.Printf("(%d, %d)\n", i, j)
        }
    }
}

第四章:复合数据类型

4.1 数组和切片

数组
package main

import "fmt"

func main() {
    // 固定长度数组
    var numbers [5]int
    numbers[0] = 1
    numbers[1] = 2
    numbers[2] = 3
    numbers[3] = 4
    numbers[4] = 5
    
    // 初始化数组
    letters := [3]string{"a", "b", "c"}
    primes := [...]int{2, 3, 5, 7, 11} // 编译器推断长度
    
    // 多维数组
    matrix := [2][3]int{
        {1, 2, 3},
        {4, 5, 6},
    }
    
    fmt.Println(numbers)
    fmt.Println(letters)
    fmt.Println(primes)
    fmt.Println(matrix)
    
    // 数组长度
    fmt.Printf("Numbers length: %d\n", len(numbers))
    fmt.Printf("Letters length: %d\n", len(letters))
    
    // 数组是值类型(复制整个数组)
    original := [3]int{1, 2, 3}
    copy := original
    copy[0] = 999
    fmt.Println("Original:", original) // [1 2 3]
    fmt.Println("Copy:", copy)         // [999 2 3]
}
切片
package main

import "fmt"

func main() {
    // 从数组创建切片
    numbers := [5]int{1, 2, 3, 4, 5}
    slice1 := numbers[1:4] // [2 3 4]
    slice2 := numbers[:3]  // [1 2 3]
    slice3 := numbers[2:]  // [3 4 5]
    
    // 直接创建切片
    fruits := []string{"apple", "banana", "orange"}
    emptySlice := []int{} // 空切片
    
    // 使用make创建切片
    scores := make([]int, 3)        // 长度3,容量3
    buffer := make([]byte, 0, 1024) // 长度0,容量1024
    
    fmt.Println(slice1, slice2, slice3)
    fmt.Println(fruits, emptySlice)
    fmt.Println(scores, buffer)
    
    // 切片操作
    data := []int{1, 2, 3, 4, 5}
    
    // 追加元素
    data = append(data, 6)
    data = append(data, 7, 8, 9)
    
    // 追加另一个切片
    moreData := []int{10, 11, 12}
    data = append(data, moreData...)
    
    // 复制切片
    copied := make([]int, len(data))
    copy(copied, data)
    
    // 切片容量和长度
    fmt.Printf("Length: %d, Capacity: %d\n", len(data), cap(data))
    
    // 动态扩容
    small := make([]int, 0, 2)
    fmt.Printf("Initial: len=%d, cap=%d\n", len(small), cap(small))
    
    for i := 0; i < 10; i++ {
        small = append(small, i)
        fmt.Printf("After append %d: len=%d, cap=%d\n", i, len(small), cap(small))
    }
    
    // 切片是引用类型
    originalSlice := []int{1, 2, 3}
    modifiedSlice := originalSlice
    modifiedSlice[0] = 999
    fmt.Println("Original slice:", originalSlice) // [999 2 3]
    fmt.Println("Modified slice:", modifiedSlice) // [999 2 3]
}

4.2 Map

package main

import "fmt"

func main() {
    // 创建map
    ages := make(map[string]int)
    scores := map[string]int{
        "Alice": 95,
        "Bob":   87,
        "Carol": 92,
    }
    
    // 添加/更新元素
    ages["Alice"] = 25
    ages["Bob"] = 30
    ages["Alice"] = 26 // 更新
    
    // 访问元素
    aliceAge := ages["Alice"]
    unknownAge := ages["Charlie"] // 返回零值(0)
    
    // 检查键是否存在
    if age, exists := ages["Alice"]; exists {
        fmt.Printf("Alice is %d years old\n", age)
    }
    
    if _, exists := ages["Charlie"]; !exists {
        fmt.Println("Charlie not found")
    }
    
    // 删除元素
    delete(ages, "Bob")
    
    // 遍历map
    for name, age := range ages {
        fmt.Printf("%s: %d\n", name, age)
    }
    
    // map长度
    fmt.Printf("Number of people: %d\n", len(ages))
    
    // map是引用类型
    originalMap := map[string]int{"a": 1, "b": 2}
    copiedMap := originalMap
    copiedMap["a"] = 999
    fmt.Println("Original map:", originalMap) // map[a:999 b:2]
    fmt.Println("Copied map:", copiedMap)     // map[a:999 b:2]
    
    // 嵌套map
    nested := map[string]map[string]int{
        "math": {
            "Alice": 95,
            "Bob":   87,
        },
        "science": {
            "Alice": 88,
            "Carol": 92,
        },
    }
    
    fmt.Println(nested["math"]["Alice"]) // 95
}

4.3 结构体

package main

import "fmt"

// 基本结构体
type Person struct {
    Name string
    Age  int
    City string
}

// 嵌套结构体
type Address struct {
    Street string
    City   string
    Zip    string
}

type Employee struct {
    Person   // 匿名字段(嵌入)
    ID       int
    Salary   float64
    Address  // 嵌入Address
}

// 带标签的结构体(用于JSON等)
type User struct {
    ID       int    `json:"id"`
    Username string `json:"username"`
    Email    string `json:"email"`
    Active   bool   `json:"active"`
}

func main() {
    // 创建结构体实例
    person1 := Person{Name: "Alice", Age: 25, City: "New York"}
    person2 := Person{"Bob", 30, "Los Angeles"} // 位置初始化(不推荐)
    
    // 访问字段
    fmt.Printf("%s is %d years old\n", person1.Name, person1.Age)
    
    // 修改字段
    person1.Age = 26
    
    // 嵌套结构体
    employee := Employee{
        Person: Person{Name: "Carol", Age: 35, City: "Chicago"},
        ID:     123,
        Salary: 75000.50,
        Address: Address{
            Street: "123 Main St",
            City:   "Chicago",
            Zip:    "60601",
        },
    }
    
    // 访问嵌入字段
    fmt.Printf("Employee: %s (ID: %d)\n", employee.Name, employee.ID)
    fmt.Printf("Address: %s, %s %s\n", employee.Street, employee.City, employee.Zip)
    
    // 结构体指针
    personPtr := &person1
    personPtr.Age = 27 // 直接修改原结构体
    
    // 结构体是值类型
    original := Person{Name: "David", Age: 40}
    copied := original
    copied.Age = 41
    fmt.Println("Original:", original) // {David 40 }
    fmt.Println("Copied:", copied)     // {David 41 }
}

第五章:函数和方法

5.1 函数基础

package main

import (
    "errors"
    "fmt"
)

// 基本函数
func add(a int, b int) int {
    return a + b
}

// 参数类型简写
func multiply(a, b int) int {
    return a * b
}

// 多返回值
func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("division by zero")
    }
    return a / b, nil
}

// 命名返回值
func calculate(a, b int) (sum, difference int) {
    sum = a + b
    difference = a - b
    return // naked return
}

// 可变参数
func sum(numbers ...int) int {
    total := 0
    for _, num := range numbers {
        total += num
    }
    return total
}

// 函数作为参数
func applyOperation(a, b int, operation func(int, int) int) int {
    return operation(a, b)
}

// 函数作为返回值
func createMultiplier(factor int) func(int) int {
    return func(x int) int {
        return x * factor
    }
}

func main() {
    // 调用基本函数
    result1 := add(5, 3)
    result2 := multiply(4, 7)
    fmt.Println(result1, result2) // 8 28
    
    // 多返回值处理
    quotient, err := divide(10, 2)
    if err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Println("Quotient:", quotient) // 5
    }
    
    // 命名返回值
    s, d := calculate(10, 3)
    fmt.Println("Sum:", s, "Difference:", d) // 13 7
    
    // 可变参数
    total := sum(1, 2, 3, 4, 5)
    fmt.Println("Total:", total) // 15
    
    // 函数作为参数
    result3 := applyOperation(10, 5, add)
    result4 := applyOperation(10, 5, multiply)
    fmt.Println(result3, result4) // 15 50
    
    // 函数作为返回值
    double := createMultiplier(2)
    triple := createMultiplier(3)
    fmt.Println(double(5), triple(5)) // 10 15
    
    // 匿名函数
    greet := func(name string) string {
        return "Hello, " + name + "!"
    }
    fmt.Println(greet("Alice")) // Hello, Alice!
    
    // 立即调用函数表达式 (IIFE)
    result5 := func(x, y int) int {
        return x * x + y * y
    }(3, 4)
    fmt.Println(result5) // 25
}

5.2 方法

package main

import "fmt"

// 结构体定义
type Rectangle struct {
    Width, Height float64
}

type Circle struct {
    Radius float64
}

// 方法定义(接收者)
func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

func (r Rectangle) Perimeter() float64 {
    return 2 * (r.Width + r.Height)
}

// 指针接收者(可以修改接收者)
func (r *Rectangle) Scale(factor float64) {
    r.Width *= factor
    r.Height *= factor
}

// Circle的方法
func (c Circle) Area() float64 {
    return 3.14159 * c.Radius * c.Radius
}

func (c Circle) Circumference() float64 {
    return 2 * 3.14159 * c.Radius
}

// 接口实现
type Shape interface {
    Area() float64
}

func printArea(s Shape) {
    fmt.Printf("Area: %.2f\n", s.Area())
}

func main() {
    // 创建实例
    rect := Rectangle{Width: 5, Height: 3}
    circle := Circle{Radius: 4}
    
    // 调用方法
    fmt.Printf("Rectangle area: %.2f\n", rect.Area())
    fmt.Printf("Rectangle perimeter: %.2f\n", rect.Perimeter())
    
    fmt.Printf("Circle area: %.2f\n", circle.Area())
    fmt.Printf("Circle circumference: %.2f\n", circle.Circumference())
    
    // 指针接收者方法
    fmt.Printf("Before scaling: %+v\n", rect)
    rect.Scale(2)
    fmt.Printf("After scaling: %+v\n", rect)
    
    // 接口使用
    printArea(rect)
    printArea(circle)
    
    // 方法值和方法表达式
    areaFunc := rect.Area
    fmt.Printf("Area via method value: %.2f\n", areaFunc())
    
    perimeterFunc := Rectangle.Perimeter
    fmt.Printf("Perimeter via method expression: %.2f\n", perimeterFunc(rect))
}

5.3 错误处理

package main

import (
    "errors"
    "fmt"
    "os"
)

// 自定义错误类型
type ValidationError struct {
    Field   string
    Message string
}

func (e ValidationError) Error() string {
    return fmt.Sprintf("validation error in field '%s': %s", e.Field, e.Message)
}

// 业务错误
type InsufficientFundsError struct {
    Balance float64
    Amount  float64
}

func (e InsufficientFundsError) Error() string {
    return fmt.Sprintf("insufficient funds: balance=%.2f, requested=%.2f", e.Balance, e.Amount)
}

// 函数返回错误
func validateEmail(email string) error {
    if email == "" {
        return ValidationError{Field: "email", Message: "cannot be empty"}
    }
    if !contains(email, "@") {
        return ValidationError{Field: "email", Message: "must contain @"}
    }
    return nil
}

func withdraw(balance, amount float64) (float64, error) {
    if amount <= 0 {
        return balance, ValidationError{Field: "amount", Message: "must be positive"}
    }
    if amount > balance {
        return balance, InsufficientFundsError{Balance: balance, Amount: amount}
    }
    return balance - amount, nil
}

// 错误包装(Go 1.13+)
func processFile(filename string) error {
    file, err := os.Open(filename)
    if err != nil {
        return fmt.Errorf("failed to open file %s: %w", filename, err)
    }
    defer file.Close()
    
    // 处理文件...
    return nil
}

func contains(s, substr string) bool {
    return len(s) >= len(substr) && (s == substr || contains(s[1:], substr))
}

func main() {
    // 基本错误处理
    email := "invalid-email"
    if err := validateEmail(email); err != nil {
        fmt.Println("Validation failed:", err)
    }
    
    // 业务错误处理
    balance := 100.0
    amount := 150.0
    newBalance, err := withdraw(balance, amount)
    if err != nil {
        if insuffErr, ok := err.(InsufficientFundsError); ok {
            fmt.Printf("Insufficient funds: balance=%.2f, amount=%.2f\n", 
                insuffErr.Balance, insuffErr.Amount)
        } else {
            fmt.Println("Other error:", err)
        }
    } else {
        fmt.Printf("Withdrawal successful. New balance: %.2f\n", newBalance)
    }
    
    // 错误包装和解包
    if err := processFile("nonexistent.txt"); err != nil {
        fmt.Println("Process failed:", err)
        
        // 检查特定错误类型
        if os.IsNotExist(err) {
            fmt.Println("File does not exist")
        }
        
        // 解包错误
        var pathError *os.PathError
        if errors.As(err, &pathError) {
            fmt.Printf("Path error: %s (operation: %s)\n", 
                pathError.Path, pathError.Op)
        }
    }
    
    // 错误比较
    err1 := ValidationError{Field: "email", Message: "cannot be empty"}
    err2 := ValidationError{Field: "email", Message: "cannot be empty"}
    fmt.Println("Errors equal:", errors.Is(err1, err2)) // false (different instances)
    
    // 使用errors.Is进行错误比较(Go 1.13+)
    var ErrEmptyEmail = errors.New("email cannot be empty")
    err3 := ErrEmptyEmail
    fmt.Println("Standard error comparison:", errors.Is(err3, ErrEmptyEmail)) // true
}

第六章:接口和泛型

6.1 接口基础

package main

import "fmt"

// 基本接口
type Speaker interface {
    Speak() string
}

type Animal interface {
    Name() string
    Sound() string
}

// 实现接口的结构体
type Dog struct {
    Name string
}

func (d Dog) Speak() string {
    return "Woof!"
}

func (d Dog) Name() string {
    return d.Name
}

func (d Dog) Sound() string {
    return "Woof"
}

type Cat struct {
    Name string
}

func (c Cat) Speak() string {
    return "Meow!"
}

func (c Cat) Name() string {
    return c.Name
}

func (c Cat) Sound() string {
    return "Meow"
}

// 接口组合
type Pet interface {
    Animal
    Play() string
}

type Bird struct {
    Name string
}

func (b Bird) Name() string {
    return b.Name
}

func (b Bird) Sound() string {
    return "Chirp"
}

func (b Bird) Play() string {
    return "Flying around"
}

func (b Bird) Speak() string {
    return "Tweet!"
}

// 空接口
func printAnything(v interface{}) {
    fmt.Printf("Value: %v, Type: %T\n", v, v)
}

// 类型断言
func describeAnimal(a Animal) {
    fmt.Printf("%s says %s\n", a.Name(), a.Sound())
    
    // 类型断言
    switch animal := a.(type) {
    case Dog:
        fmt.Println("It's a dog!")
    case Cat:
        fmt.Println("It's a cat!")
    default:
        fmt.Println("Unknown animal")
    }
}

func main() {
    // 使用接口
    var speaker Speaker
    speaker = Dog{Name: "Buddy"}
    fmt.Println(speaker.Speak()) // Woof!
    
    speaker = Cat{Name: "Whiskers"}
    fmt.Println(speaker.Speak()) // Meow!
    
    // 接口切片
    animals := []Animal{
        Dog{Name: "Rex"},
        Cat{Name: "Fluffy"},
        Bird{Name: "Tweety"},
    }
    
    for _, animal := range animals {
        describeAnimal(animal)
    }
    
    // 接口组合
    var pet Pet = Bird{Name: "Polly"}
    fmt.Println(pet.Name(), pet.Sound(), pet.Play())
    
    // 空接口
    printAnything(42)
    printAnything("hello")
    printAnything(true)
    printAnything([]int{1, 2, 3})
    
    // 接口值和动态类型
    var any interface{} = "hello"
    fmt.Println(any) // hello
    
    any = 42
    fmt.Println(any) // 42
    
    // 检查接口是否为nil
    var speaker2 Speaker
    if speaker2 == nil {
        fmt.Println("speaker2 is nil")
    }
}

6.2 泛型(Go 1.18+)

package main

import (
    "fmt"
    "golang.org/x/exp/constraints"
)

// 基本泛型函数
func min[T constraints.Ordered](a, b T) T {
    if a < b {
        return a
    }
    return b
}

func max[T constraints.Ordered](a, b T) T {
    if a > b {
        return a
    }
    return b
}

// 泛型切片操作
func indexOf[T comparable](slice []T, target T) int {
    for i, v := range slice {
        if v == target {
            return i
        }
    }
    return -1
}

func contains[T comparable](slice []T, target T) bool {
    return indexOf(slice, target) != -1
}

func filter[T any](slice []T, predicate func(T) bool) []T {
    var result []T
    for _, v := range slice {
        if predicate(v) {
            result = append(result, v)
        }
    }
    return result
}

// 泛型结构体
type Stack[T any] struct {
    items []T
}

func (s *Stack[T]) Push(item T) {
    s.items = append(s.items, item)
}

func (s *Stack[T]) Pop() (T, bool) {
    var zero T
    if len(s.items) == 0 {
        return zero, false
    }
    item := s.items[len(s.items)-1]
    s.items = s.items[:len(s.items)-1]
    return item, true
}

func (s *Stack[T]) Peek() (T, bool) {
    var zero T
    if len(s.items) == 0 {
        return zero, false
    }
    return s.items[len(s.items)-1], true
}

func (s *Stack[T]) Size() int {
    return len(s.items)
}

// 泛型接口
type Number interface {
    constraints.Integer | constraints.Float
}

func sum[T Number](numbers []T) T {
    var total T
    for _, n := range numbers {
        total += n
    }
    return total
}

// 泛型约束组合
type Stringer interface {
    String() string
}

type Printable interface {
    Stringer
    comparable
}

// 泛型方法
type Container[T any] struct {
    value T
}

func (c Container[T]) GetValue() T {
    return c.value
}

func (c *Container[T]) SetValue(value T) {
    c.value = value
}

func main() {
    // 基本泛型函数
    fmt.Println(min(5, 3))           // 3
    fmt.Println(min(3.14, 2.71))     // 2.71
    fmt.Println(max("apple", "banana")) // banana
    
    // 泛型切片操作
    numbers := []int{1, 2, 3, 4, 5}
    fmt.Println(indexOf(numbers, 3))    // 2
    fmt.Println(contains(numbers, 6))   // false
    
    evens := filter(numbers, func(n int) bool {
        return n%2 == 0
    })
    fmt.Println(evens) // [2 4]
    
    // 泛型结构体
    intStack := &Stack[int]{}
    intStack.Push(1)
    intStack.Push(2)
    intStack.Push(3)
    
    for intStack.Size() > 0 {
        if item, ok := intStack.Pop(); ok {
            fmt.Println("Popped:", item)
        }
    }
    
    stringStack := &Stack[string]{}
    stringStack.Push("hello")
    stringStack.Push("world")
    
    if top, ok := stringStack.Peek(); ok {
        fmt.Println("Top:", top) // world
    }
    
    // 泛型接口
    intSum := sum([]int{1, 2, 3, 4, 5})
    floatSum := sum([]float64{1.1, 2.2, 3.3})
    fmt.Println(intSum, floatSum) // 15 6.6
    
    // 泛型容器
    container := Container[string]{value: "initial"}
    fmt.Println("Initial value:", container.GetValue())
    
    container.SetValue("updated")
    fmt.Println("Updated value:", container.GetValue())
}

6.3 接口最佳实践

package main

import (
    "context"
    "fmt"
    "io"
    "time"
)

// 小接口原则
type Reader interface {
    Read(p []byte) (n int, err error)
}

type Writer interface {
    Write(p []byte) (n int, err error)
}

type Closer interface {
    Close() error
}

// 接口组合
type ReadCloser interface {
    Reader
    Closer
}

type WriteCloser interface {
    Writer
    Closer
}

type ReadWriteCloser interface {
    Reader
    Writer
    Closer
}

// 上下文接口
type Service interface {
    Process(ctx context.Context, input string) (string, error)
}

// 模拟服务实现
type MockService struct{}

func (m MockService) Process(ctx context.Context, input string) (string, error) {
    select {
    case <-ctx.Done():
        return "", ctx.Err()
    case <-time.After(100 * time.Millisecond):
        return "processed: " + input, nil
    }
}

// 依赖注入
type Processor struct {
    service Service
}

func NewProcessor(service Service) *Processor {
    return &Processor{service: service}
}

func (p *Processor) Handle(input string) (string, error) {
    ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
    defer cancel()
    
    return p.service.Process(ctx, input)
}

// 接口模拟(用于测试)
type MockReader struct {
    Data []byte
    Pos  int
}

func (m *MockReader) Read(p []byte) (n int, err error) {
    if m.Pos >= len(m.Data) {
        return 0, io.EOF
    }
    n = copy(p, m.Data[m.Pos:])
    m.Pos += n
    return n, nil
}

func (m *MockReader) Close() error {
    m.Pos = 0
    return nil
}

// 接口适配器
type StringReader struct {
    str string
    pos int
}

func (s *StringReader) Read(p []byte) (n int, err error) {
    if s.pos >= len(s.str) {
        return 0, io.EOF
    }
    n = copy(p, s.str[s.pos:])
    s.pos += n
    return n, nil
}

func main() {
    // 小接口使用
    var reader Reader = &StringReader{str: "Hello, World!"}
    buffer := make([]byte, 5)
    n, err := reader.Read(buffer)
    fmt.Printf("Read %d bytes: %s, error: %v\n", n, buffer[:n], err)
    
    // 依赖注入
    mockService := MockService{}
    processor := NewProcessor(mockService)
    
    result, err := processor.Handle("test input")
    if err != nil {
        fmt.Println("Error:", err) // context deadline exceeded
    } else {
        fmt.Println("Result:", result)
    }
    
    // 接口模拟
    mockReader := &MockReader{Data: []byte("mock data")}
    data := make([]byte, 10)
    n, err = mockReader.Read(data)
    fmt.Printf("Mock read %d bytes: %s, error: %v\n", n, data[:n], err)
    
    // 接口组合
    var rc ReadCloser = mockReader
    rc.Close()
}

第七章:并发编程

7.1 Goroutine基础

package main

import (
    "fmt"
    "time"
)

func say(s string) {
    for i := 0; i < 5; i++ {
        time.Sleep(100 * time.Millisecond)
        fmt.Println(s)
    }
}

func main() {
    // 启动goroutine
    go say("world")
    say("hello")
    
    // 等待goroutine完成(简单方式)
    time.Sleep(600 * time.Millisecond)
    
    // 更好的同步方式
    done := make(chan bool)
    
    go func() {
        fmt.Println("Goroutine starting")
        time.Sleep(500 * time.Millisecond)
        fmt.Println("Goroutine finished")
        done <- true
    }()
    
    fmt.Println("Main waiting")
    <-done
    fmt.Println("Main finished")
}

7.2 Channel

package main

import (
    "fmt"
    "time"
)

func main() {
    // 无缓冲channel
    ch := make(chan int)
    
    go func() {
        fmt.Println("Sending 42")
        ch <- 42
        fmt.Println("Sent 42")
    }()
    
    fmt.Println("Receiving...")
    value := <-ch
    fmt.Printf("Received: %d\n", value)
    
    // 带缓冲channel
    bufferedCh := make(chan string, 2)
    bufferedCh <- "first"
    bufferedCh <- "second"
    // bufferedCh <- "third" // 这会阻塞,因为缓冲区已满
    
    fmt.Println(<-bufferedCh) // first
    fmt.Println(<-bufferedCh) // second
    
    // channel方向
    sendOnly := make(chan<- int)
    receiveOnly := make(<-chan int)
    
    // 实际使用中通常在函数参数中指定方向
    go sendData(sendOnly)
    receiveData(receiveOnly)
    
    // select语句
    ch1 := make(chan string)
    ch2 := make(chan string)
    
    go func() {
        time.Sleep(100 * time.Millisecond)
        ch1 <- "from ch1"
    }()
    
    go func() {
        time.Sleep(200 * time.Millisecond)
        ch2 <- "from ch2"
    }()
    
    for i := 0; i < 2; i++ {
        select {
        case msg1 := <-ch1:
            fmt.Println("Received from ch1:", msg1)
        case msg2 := <-ch2:
            fmt.Println("Received from ch2:", msg2)
        case <-time.After(300 * time.Millisecond):
            fmt.Println("Timeout")
        }
    }
    
    // 关闭channel
    jobs := make(chan int, 5)
    done := make(chan bool)
    
    go func() {
        for {
            j, more := <-jobs
            if more {
                fmt.Println("Received job", j)
            } else {
                fmt.Println("No more jobs")
                done <- true
                return
            }
        }
    }()
    
    for j := 1; j <= 3; j++ {
        jobs <- j
        fmt.Println("Sent job", j)
    }
    close(jobs)
    fmt.Println("Sent all jobs")
    
    <-done
}

func sendData(ch chan<- int) {
    ch <- 100
}

func receiveData(ch <-chan int) {
    value := <-ch
    fmt.Println("Received:", value)
}

7.3 同步原语

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    // WaitGroup
    var wg sync.WaitGroup
    
    for i := 1; i <= 3; i++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            fmt.Printf("Worker %d starting\n", id)
            time.Sleep(time.Duration(id) * time.Second)
            fmt.Printf("Worker %d finished\n", id)
        }(i)
    }
    
    wg.Wait()
    fmt.Println("All workers finished")
    
    // Mutex
    var counter int
    var mutex sync.Mutex
    
    var wg2 sync.WaitGroup
    for i := 0; i < 1000; i++ {
        wg2.Add(1)
        go func() {
            defer wg2.Done()
            mutex.Lock()
            counter++
            mutex.Unlock()
        }()
    }
    
    wg2.Wait()
    fmt.Printf("Final counter: %d\n", counter)
    
    // RWMutex
    var data = make(map[string]int)
    var rwMutex sync.RWMutex
    
    // 读操作
    go func() {
        rwMutex.RLock()
        value := data["key"]
        rwMutex.RUnlock()
        fmt.Printf("Read value: %d\n", value)
    }()
    
    // 写操作
    rwMutex.Lock()
    data["key"] = 42
    rwMutex.Unlock()
    
    // Once
    var once sync.Once
    var initialized bool
    
    for i := 0; i < 5; i++ {
        go func(id int) {
            once.Do(func() {
                fmt.Printf("Initializing (called by goroutine %d)\n", id)
                initialized = true
            })
            fmt.Printf("Goroutine %d: initialized = %t\n", id, initialized)
        }(i)
    }
    
    time.Sleep(100 * time.Millisecond)
    
    // Pool
    var pool = sync.Pool{
        New: func() interface{} {
            fmt.Println("Creating new object")
            return &struct{ value int }{value: 0}
        },
    }
    
    // 获取对象
    obj1 := pool.Get().(*struct{ value int })
    obj1.value = 42
    fmt.Printf("Got object with value: %d\n", obj1.value)
    
    // 归还对象
    pool.Put(obj1)
    
    // 再次获取(可能重用)
    obj2 := pool.Get().(*struct{ value int })
    fmt.Printf("Got object with value: %d\n", obj2.value)
}

7.4 高级并发模式

package main

import (
    "context"
    "fmt"
    "sync"
    "time"
)

// Worker Pool模式
func worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) {
    defer wg.Done()
    for job := range jobs {
        fmt.Printf("Worker %d processing job %d\n", id, job)
        time.Sleep(time.Second) // 模拟工作
        results <- job * 2
    }
}

// Fan-out/Fan-in模式
func fanOutFanIn() {
    // 生成器
    gen := func(nums ...int) <-chan int {
        out := make(chan int)
        go func() {
            defer close(out)
            for _, n := range nums {
                out <- n
            }
        }()
        return out
    }
    
    // 平方函数
    sq := func(in <-chan int) <-chan int {
        out := make(chan int)
        go func() {
            defer close(out)
            for n := range in {
                out <- n * n
            }
        }()
        return out
    }
    
    // 合并函数
    merge := func(cs ...<-chan int) <-chan int {
        var wg sync.WaitGroup
        out := make(chan int)
        
        output := func(c <-chan int) {
            defer wg.Done()
            for n := range c {
                out <- n
            }
        }
        
        wg.Add(len(cs))
        for _, c := range cs {
            go output(c)
        }
        
        go func() {
            wg.Wait()
            close(out)
        }()
        
        return out
    }
    
    // 使用
    in := gen(2, 3, 4, 5)
    c1 := sq(in)
    c2 := sq(in)
    
    for n := range merge(c1, c2) {
        fmt.Println(n) // 4, 9, 16, 25 (顺序可能不同)
    }
}

// Context取消模式
func doWork(ctx context.Context, id int) {
    for {
        select {
        case <-ctx.Done():
            fmt.Printf("Worker %d cancelled: %v\n", id, ctx.Err())
            return
        default:
            fmt.Printf("Worker %d working...\n", id)
            time.Sleep(500 * time.Millisecond)
        }
    }
}

// 生产者-消费者模式
func producerConsumer() {
    jobs := make(chan int, 100)
    results := make(chan int, 100)
    
    // 生产者
    go func() {
        defer close(jobs)
        for i := 1; i <= 10; i++ {
            jobs <- i
            fmt.Printf("Produced job %d\n", i)
        }
    }()
    
    // 消费者
    var wg sync.WaitGroup
    for w := 1; w <= 3; w++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            for job := range jobs {
                result := job * job
                fmt.Printf("Worker %d processed job %d, result: %d\n", id, job, result)
                results <- result
            }
        }(w)
    }
    
    // 等待所有消费者完成
    go func() {
        wg.Wait()
        close(results)
    }()
    
    // 收集结果
    for result := range results {
        fmt.Printf("Collected result: %d\n", result)
    }
}

func main() {
    // Worker Pool
    fmt.Println("=== Worker Pool ===")
    jobs := make(chan int, 100)
    results := make(chan int, 100)
    
    var wg sync.WaitGroup
    for w := 1; w <= 3; w++ {
        wg.Add(1)
        go worker(w, jobs, results, &wg)
    }
    
    // 发送工作
    for j := 1; j <= 5; j++ {
        jobs <- j
    }
    close(jobs)
    
    wg.Wait()
    close(results)
    
    for result := range results {
        fmt.Printf("Result: %d\n", result)
    }
    
    // Fan-out/Fan-in
    fmt.Println("\n=== Fan-out/Fan-in ===")
    fanOutFanIn()
    
    // Context取消
    fmt.Println("\n=== Context Cancellation ===")
    ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
    defer cancel()
    
    go doWork(ctx, 1)
    go doWork(ctx, 2)
    
    time.Sleep(3 * time.Second)
    
    // 生产者-消费者
    fmt.Println("\n=== Producer-Consumer ===")
    producerConsumer()
}

第八章:包管理和模块

8.1 Go Modules

# 初始化新模块
go mod init myproject

# 添加依赖
go get github.com/gin-gonic/gin@latest
go get github.com/sirupsen/logrus@v1.9.0

# 更新依赖
go get -u github.com/gin-gonic/gin
go get -u ./... # 更新所有依赖

# 清理未使用的依赖
go mod tidy

# 查看依赖图
go mod graph

# 验证依赖
go mod verify

# 下载依赖到本地缓存
go mod download

8.2 go.mod文件

// go.mod
module myproject

go 1.25

require (
    github.com/gin-gonic/gin v1.10.0
    github.com/sirupsen/logrus v1.9.3
    golang.org/x/crypto v0.21.0
)

// 排除特定版本
exclude github.com/bad/package v1.0.0

// 替换依赖(用于本地开发或私有仓库)
replace github.com/my/private-lib => ../private-lib
replace github.com/old/package => github.com/new/package v2.0.0

// 间接依赖(通常由go mod tidy自动生成)
indirect

8.3 工作区模式(Go 1.18+)

# 创建工作区
go work init
go work use ./myproject
go work use ./shared-lib

# 工作区文件 (go.work)
go 1.25

use (
    ./myproject
    ./shared-lib
)

replace github.com/my/shared-lib => ./shared-lib

8.4 私有模块

# 配置私有模块
git config --global url."https://git.example.com".insteadOf "https://example.com"

# 或者设置GOPRIVATE环境变量
export GOPRIVATE=example.com/myorg/*

# 在go.mod中使用
require example.com/myorg/mymodule v1.0.0

第九章:测试和基准测试

9.1 单元测试

// math.go
package main

func Add(a, b int) int {
    return a + b
}

func Divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, fmt.Errorf("division by zero")
    }
    return a / b, nil
}

// math_test.go
package main

import (
    "testing"
)

func TestAdd(t *testing.T) {
    tests := []struct {
        name     string
        a, b     int
        expected int
    }{
        {"positive numbers", 2, 3, 5},
        {"negative numbers", -2, -3, -5},
        {"mixed numbers", 2, -3, -1},
        {"zero", 0, 0, 0},
    }
    
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            result := Add(tt.a, tt.b)
            if result != tt.expected {
                t.Errorf("Add(%d, %d) = %d; expected %d", tt.a, tt.b, result, tt.expected)
            }
        })
    }
}

func TestDivide(t *testing.T) {
    tests := []struct {
        name        string
        a, b        float64
        expected    float64
        expectError bool
    }{
        {"normal division", 10, 2, 5, false},
        {"division by zero", 10, 0, 0, true},
        {"negative numbers", -10, 2, -5, false},
    }
    
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            result, err := Divide(tt.a, tt.b)
            if tt.expectError {
                if err == nil {
                    t.Error("Expected error but got none")
                }
            } else {
                if err != nil {
                    t.Errorf("Unexpected error: %v", err)
                }
                if result != tt.expected {
                    t.Errorf("Divide(%f, %f) = %f; expected %f", tt.a, tt.b, result, tt.expected)
                }
            }
        })
    }
}

func TestMain(m *testing.M) {
    // 测试前设置
    setup()
    
    // 运行测试
    code := m.Run()
    
    // 测试后清理
    cleanup()
    
    os.Exit(code)
}

9.2 基准测试

// benchmark_test.go
package main

import (
    "strconv"
    "testing"
)

func BenchmarkAdd(b *testing.B) {
    for i := 0; i < b.N; i++ {
        Add(1, 2)
    }
}

func BenchmarkStringConcat(b *testing.B) {
    s1, s2 := "hello", "world"
    
    b.Run("plus", func(b *testing.B) {
        for i := 0; i < b.N; i++ {
            _ = s1 + " " + s2
        }
    })
    
    b.Run("sprintf", func(b *testing.B) {
        for i := 0; i < b.N; i++ {
            _ = fmt.Sprintf("%s %s", s1, s2)
        }
    })
    
    b.Run("builder", func(b *testing.B) {
        for i := 0; i < b.N; i++ {
            var builder strings.Builder
            builder.WriteString(s1)
            builder.WriteString(" ")
            builder.WriteString(s2)
            _ = builder.String()
        }
    })
}

func BenchmarkParsing(b *testing.B) {
    input := "12345"
    
    b.Run("strconv", func(b *testing.B) {
        for i := 0; i < b.N; i++ {
            _, _ = strconv.Atoi(input)
        }
    })
    
    b.Run("fmt", func(b *testing.B) {
        for i := 0; i < b.N; i++ {
            var n int
            _, _ = fmt.Sscanf(input, "%d", &n)
        }
    })
}

// 内存分配基准测试
func BenchmarkMemoryAllocation(b *testing.B) {
    b.Run("slice", func(b *testing.B) {
        for i := 0; i < b.N; i++ {
            _ = make([]int, 1000)
        }
    })
    
    b.Run("map", func(b *testing.B) {
        for i := 0; i < b.N; i++ {
            _ = make(map[string]int, 1000)
        }
    })
}

9.3 模拟和测试工具

// repository.go
package main

import (
    "context"
    "database/sql"
)

type User struct {
    ID    int
    Name  string
    Email string
}

type UserRepository interface {
    GetUserByID(ctx context.Context, id int) (*User, error)
    CreateUser(ctx context.Context, user *User) error
}

type SQLUserRepository struct {
    db *sql.DB
}

func (r *SQLUserRepository) GetUserByID(ctx context.Context, id int) (*User, error) {
    // 数据库查询实现
    return &User{ID: id, Name: "John", Email: "john@example.com"}, nil
}

func (r *SQLUserRepository) CreateUser(ctx context.Context, user *User) error {
    // 数据库插入实现
    return nil
}

// service.go
type UserService struct {
    repo UserRepository
}

func NewUserService(repo UserRepository) *UserService {
    return &UserService{repo: repo}
}

func (s *UserService) GetUserProfile(ctx context.Context, userID int) (*User, error) {
    return s.repo.GetUserByID(ctx, userID)
}

// service_test.go
package main

import (
    "context"
    "testing"
)

// Mock实现
type MockUserRepository struct {
    getUserByIDFunc func(ctx context.Context, id int) (*User, error)
    createUserFunc  func(ctx context.Context, user *User) error
}

func (m *MockUserRepository) GetUserByID(ctx context.Context, id int) (*User, error) {
    if m.getUserByIDFunc != nil {
        return m.getUserByIDFunc(ctx, id)
    }
    return nil, nil
}

func (m *MockUserRepository) CreateUser(ctx context.Context, user *User) error {
    if m.createUserFunc != nil {
        return m.createUserFunc(ctx, user)
    }
    return nil
}

func TestUserService_GetUserProfile(t *testing.T) {
    expectedUser := &User{ID: 1, Name: "Alice", Email: "alice@example.com"}
    
    mockRepo := &MockUserRepository{
        getUserByIDFunc: func(ctx context.Context, id int) (*User, error) {
            if id == 1 {
                return expectedUser, nil
            }
            return nil, fmt.Errorf("user not found")
        },
    }
    
    service := NewUserService(mockRepo)
    
    user, err := service.GetUserProfile(context.Background(), 1)
    if err != nil {
        t.Fatalf("Expected no error, got %v", err)
    }
    
    if user.ID != expectedUser.ID || user.Name != expectedUser.Name {
        t.Errorf("Expected user %+v, got %+v", expectedUser, user)
    }
    
    // 测试错误情况
    _, err = service.GetUserProfile(context.Background(), 999)
    if err == nil {
        t.Error("Expected error for non-existent user")
    }
}

// 使用testify/mock(第三方库)
// go get github.com/stretchr/testify/mock

import (
    "github.com/stretchr/testify/mock"
)

type MockUserRepository2 struct {
    mock.Mock
}

func (m *MockUserRepository2) GetUserByID(ctx context.Context, id int) (*User, error) {
    args := m.Called(ctx, id)
    return args.Get(0).(*User), args.Error(1)
}

func (m *MockUserRepository2) CreateUser(ctx context.Context, user *User) error {
    args := m.Called(ctx, user)
    return args.Error(0)
}

func TestUserServiceWithTestify(t *testing.T) {
    mockRepo := new(MockUserRepository2)
    expectedUser := &User{ID: 1, Name: "Bob", Email: "bob@example.com"}
    
    mockRepo.On("GetUserByID", mock.Anything, 1).Return(expectedUser, nil)
    
    service := NewUserService(mockRepo)
    user, err := service.GetUserProfile(context.Background(), 1)
    
    if err != nil {
        t.Fatalf("Expected no error, got %v", err)
    }
    
    if user.Name != "Bob" {
        t.Errorf("Expected Bob, got %s", user.Name)
    }
    
    mockRepo.AssertExpectations(t)
}

9.4 代码覆盖率

# 运行测试并生成覆盖率报告
go test -coverprofile=coverage.out ./...

# 在浏览器中查看覆盖率
go tool cover -html=coverage.out

# 显示覆盖率百分比
go test -cover ./...

# 按函数显示覆盖率
go tool cover -func=coverage.out

第十章:Web开发

10.1 标准库HTTP服务器

// server.go
package main

import (
    "encoding/json"
    "fmt"
    "log"
    "net/http"
    "strconv"
    "time"
)

type User struct {
    ID    int    `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

var users = []User{
    {ID: 1, Name: "Alice", Email: "alice@example.com"},
    {ID: 2, Name: "Bob", Email: "bob@example.com"},
}

func healthHandler(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("OK"))
}

func getUsersHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(users)
}

func getUserHandler(w http.ResponseWriter, r *http.Request) {
    idStr := r.URL.Query().Get("id")
    if idStr == "" {
        http.Error(w, "Missing id parameter", http.StatusBadRequest)
        return
    }
    
    id, err := strconv.Atoi(idStr)
    if err != nil {
        http.Error(w, "Invalid id parameter", http.StatusBadRequest)
        return
    }
    
    for _, user := range users {
        if user.ID == id {
            w.Header().Set("Content-Type", "application/json")
            json.NewEncoder(w).Encode(user)
            return
        }
    }
    
    http.Error(w, "User not found", http.StatusNotFound)
}

func createUserHandler(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodPost {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }
    
    var newUser User
    if err := json.NewDecoder(r.Body).Decode(&newUser); err != nil {
        http.Error(w, "Invalid JSON", http.StatusBadRequest)
        return
    }
    
    // 简单的ID生成
    newUser.ID = len(users) + 1
    users = append(users, newUser)
    
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusCreated)
    json.NewEncoder(w).Encode(newUser)
}

func middleware(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        start := time.Now()
        log.Printf("Started %s %s", r.Method, r.URL.Path)
        
        next.ServeHTTP(w, r)
        
        log.Printf("Completed %s %s in %v", r.Method, r.URL.Path, time.Since(start))
    }
}

func main() {
    http.HandleFunc("/health", middleware(healthHandler))
    http.HandleFunc("/users", middleware(getUsersHandler))
    http.HandleFunc("/user", middleware(getUserHandler))
    http.HandleFunc("/user/create", middleware(createUserHandler))
    
    log.Println("Server starting on :8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

10.2 Gin框架

// gin_server.go
package main

import (
    "net/http"
    "github.com/gin-gonic/gin"
)

type CreateUserRequest struct {
    Name  string `json:"name" binding:"required"`
    Email string `json:"email" binding:"required,email"`
}

type UserResponse struct {
    ID    int    `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

var users = []UserResponse{
    {ID: 1, Name: "Alice", Email: "alice@example.com"},
    {ID: 2, Name: "Bob", Email: "bob@example.com"},
}

func main() {
    r := gin.Default()
    
    // 健康检查
    r.GET("/health", func(c *gin.Context) {
        c.JSON(http.StatusOK, gin.H{"status": "ok"})
    })
    
    // 获取所有用户
    r.GET("/users", func(c *gin.Context) {
        c.JSON(http.StatusOK, users)
    })
    
    // 获取单个用户
    r.GET("/users/:id", func(c *gin.Context) {
        id := c.Param("id")
        for _, user := range users {
            if fmt.Sprintf("%d", user.ID) == id {
                c.JSON(http.StatusOK, user)
                return
            }
        }
        c.JSON(http.StatusNotFound, gin.H{"error": "user not found"})
    })
    
    // 创建用户
    r.POST("/users", func(c *gin.Context) {
        var req CreateUserRequest
        if err := c.ShouldBindJSON(&req); err != nil {
            c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            return
        }
        
        newUser := UserResponse{
            ID:    len(users) + 1,
            Name:  req.Name,
            Email: req.Email,
        }
        users = append(users, newUser)
        
        c.JSON(http.StatusCreated, newUser)
    })
    
    // 更新用户
    r.PUT("/users/:id", func(c *gin.Context) {
        id := c.Param("id")
        var req CreateUserRequest
        if err := c.ShouldBindJSON(&req); err != nil {
            c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            return
        }
        
        for i, user := range users {
            if fmt.Sprintf("%d", user.ID) == id {
                users[i].Name = req.Name
                users[i].Email = req.Email
                c.JSON(http.StatusOK, users[i])
                return
            }
        }
        c.JSON(http.StatusNotFound, gin.H{"error": "user not found"})
    })
    
    // 删除用户
    r.DELETE("/users/:id", func(c *gin.Context) {
        id := c.Param("id")
        for i, user := range users {
            if fmt.Sprintf("%d", user.ID) == id {
                users = append(users[:i], users[i+1:]...)
                c.JSON(http.StatusNoContent, nil)
                return
            }
        }
        c.JSON(http.StatusNotFound, gin.H{"error": "user not found"})
    })
    
    r.Run(":8080")
}

10.3 数据库操作

// database.go
package main

import (
    "context"
    "database/sql"
    "fmt"
    "log"
    "time"
    
    _ "github.com/lib/pq" // PostgreSQL driver
    // _ "github.com/go-sql-driver/mysql" // MySQL driver
)

type User struct {
    ID        int       `json:"id"`
    Name      string    `json:"name"`
    Email     string    `json:"email"`
    CreatedAt time.Time `json:"created_at"`
}

type UserRepository struct {
    db *sql.DB
}

func NewUserRepository(db *sql.DB) *UserRepository {
    return &UserRepository{db: db}
}

func (r *UserRepository) Create(ctx context.Context, user *User) error {
    query := `INSERT INTO users (name, email, created_at) VALUES ($1, $2, $3) RETURNING id`
    return r.db.QueryRowContext(ctx, query, user.Name, user.Email, time.Now()).Scan(&user.ID)
}

func (r *UserRepository) GetByID(ctx context.Context, id int) (*User, error) {
    query := `SELECT id, name, email, created_at FROM users WHERE id = $1`
    row := r.db.QueryRowContext(ctx, query, id)
    
    var user User
    err := row.Scan(&user.ID, &user.Name, &user.Email, &user.CreatedAt)
    if err != nil {
        if err == sql.ErrNoRows {
            return nil, fmt.Errorf("user not found")
        }
        return nil, err
    }
    
    return &user, nil
}

func (r *UserRepository) GetAll(ctx context.Context) ([]*User, error) {
    query := `SELECT id, name, email, created_at FROM users ORDER BY id`
    rows, err := r.db.QueryContext(ctx, query)
    if err != nil {
        return nil, err
    }
    defer rows.Close()
    
    var users []*User
    for rows.Next() {
        var user User
        if err := rows.Scan(&user.ID, &user.Name, &user.Email, &user.CreatedAt); err != nil {
            return nil, err
        }
        users = append(users, &user)
    }
    
    return users, rows.Err()
}

func (r *UserRepository) Update(ctx context.Context, user *User) error {
    query := `UPDATE users SET name = $1, email = $2 WHERE id = $3`
    result, err := r.db.ExecContext(ctx, query, user.Name, user.Email, user.ID)
    if err != nil {
        return err
    }
    
    rowsAffected, err := result.RowsAffected()
    if err != nil {
        return err
    }
    
    if rowsAffected == 0 {
        return fmt.Errorf("user not found")
    }
    
    return nil
}

func (r *UserRepository) Delete(ctx context.Context, id int) error {
    query := `DELETE FROM users WHERE id = $1`
    result, err := r.db.ExecContext(ctx, query, id)
    if err != nil {
        return err
    }
    
    rowsAffected, err := result.RowsAffected()
    if err != nil {
        return err
    }
    
    if rowsAffected == 0 {
        return fmt.Errorf("user not found")
    }
    
    return nil
}

func main() {
    // 连接数据库
    db, err := sql.Open("postgres", "host=localhost port=5432 user=postgres password=secret dbname=myapp sslmode=disable")
    if err != nil {
        log.Fatal("Failed to connect to database:", err)
    }
    defer db.Close()
    
    // 测试连接
    if err := db.Ping(); err != nil {
        log.Fatal("Failed to ping database:", err)
    }
    
    // 设置连接池
    db.SetMaxOpenConns(25)
    db.SetMaxIdleConns(5)
    db.SetConnMaxLifetime(5 * time.Minute)
    
    repo := NewUserRepository(db)
    
    ctx := context.Background()
    
    // 创建用户
    user := &User{Name: "Charlie", Email: "charlie@example.com"}
    if err := repo.Create(ctx, user); err != nil {
        log.Fatal("Failed to create user:", err)
    }
    fmt.Printf("Created user: %+v\n", user)
    
    // 获取用户
    retrievedUser, err := repo.GetByID(ctx, user.ID)
    if err != nil {
        log.Fatal("Failed to get user:", err)
    }
    fmt.Printf("Retrieved user: %+v\n", retrievedUser)
    
    // 更新用户
    retrievedUser.Name = "Charles"
    if err := repo.Update(ctx, retrievedUser); err != nil {
        log.Fatal("Failed to update user:", err)
    }
    fmt.Println("Updated user")
    
    // 获取所有用户
    allUsers, err := repo.GetAll(ctx)
    if err != nil {
        log.Fatal("Failed to get all users:", err)
    }
    fmt.Printf("All users: %+v\n", allUsers)
    
    // 删除用户
    if err := repo.Delete(ctx, user.ID); err != nil {
        log.Fatal("Failed to delete user:", err)
    }
    fmt.Println("Deleted user")
}

10.4 REST API最佳实践

// api.go
package main

import (
    "context"
    "encoding/json"
    "errors"
    "log"
    "net/http"
    "strconv"
    "time"
    
    "github.com/gin-gonic/gin"
    "github.com/gin-gonic/gin/binding"
    "github.com/go-playground/validator/v10"
)

// 全局错误类型
var (
    ErrNotFound      = errors.New("resource not found")
    ErrInvalidInput  = errors.New("invalid input")
    ErrInternal      = errors.New("internal server error")
    ErrUnauthorized  = errors.New("unauthorized")
)

// 错误响应结构
type ErrorResponse struct {
    Error   string `json:"error"`
    Message string `json:"message"`
}

// 成功响应结构
type SuccessResponse struct {
    Data interface{} `json:"data,omitempty"`
    Meta interface{} `json:"meta,omitempty"`
}

// 分页元数据
type PaginationMeta struct {
    Page       int `json:"page"`
    PageSize   int `json:"page_size"`
    Total      int `json:"total"`
    TotalPages int `json:"total_pages"`
}

// 用户模型
type User struct {
    ID        int       `json:"id" gorm:"primaryKey"`
    Name      string    `json:"name" validate:"required,min=2,max=50"`
    Email     string    `json:"email" validate:"required,email"`
    CreatedAt time.Time `json:"created_at"`
    UpdatedAt time.Time `json:"updated_at"`
}

// 请求模型
type CreateUserRequest struct {
    Name  string `json:"name" validate:"required,min=2,max=50"`
    Email string `json:"email" validate:"required,email"`
}

type UpdateUserRequest struct {
    Name  string `json:"name" validate:"required,min=2,max=50"`
    Email string `json:"email" validate:"required,email"`
}

// 服务层
type UserService interface {
    Create(ctx context.Context, req *CreateUserRequest) (*User, error)
    GetByID(ctx context.Context, id int) (*User, error)
    GetAll(ctx context.Context, page, pageSize int) ([]*User, *PaginationMeta, error)
    Update(ctx context.Context, id int, req *UpdateUserRequest) (*User, error)
    Delete(ctx context.Context, id int) error
}

// 服务实现
type userService struct {
    // userRepository UserRepository
}

func (s *userService) Create(ctx context.Context, req *CreateUserRequest) (*User, error) {
    // 验证输入
    if err := validate.Struct(req); err != nil {
        return nil, ErrInvalidInput
    }
    
    // 创建用户逻辑
    user := &User{
        Name:      req.Name,
        Email:     req.Email,
        CreatedAt: time.Now(),
        UpdatedAt: time.Now(),
    }
    
    // 保存到数据库
    // s.userRepository.Create(ctx, user)
    
    return user, nil
}

func (s *userService) GetByID(ctx context.Context, id int) (*User, error) {
    if id <= 0 {
        return nil, ErrInvalidInput
    }
    
    // 从数据库获取
    // user, err := s.userRepository.GetByID(ctx, id)
    // if err != nil {
    //     if errors.Is(err, ErrNotFound) {
    //         return nil, ErrNotFound
    //     }
    //     return nil, ErrInternal
    // }
    
    // 模拟数据
    return &User{ID: id, Name: "Test User", Email: "test@example.com"}, nil
}

func (s *userService) GetAll(ctx context.Context, page, pageSize int) ([]*User, *PaginationMeta, error) {
    if page < 1 {
        page = 1
    }
    if pageSize < 1 || pageSize > 100 {
        pageSize = 10
    }
    
    // 从数据库获取分页数据
    // users, total, err := s.userRepository.GetAll(ctx, page, pageSize)
    // if err != nil {
    //     return nil, nil, ErrInternal
    // }
    
    // 模拟数据
    users := []*User{
        {ID: 1, Name: "Alice", Email: "alice@example.com"},
        {ID: 2, Name: "Bob", Email: "bob@example.com"},
    }
    total := 2
    
    meta := &PaginationMeta{
        Page:       page,
        PageSize:   pageSize,
        Total:      total,
        TotalPages: (total + pageSize - 1) / pageSize,
    }
    
    return users, meta, nil
}

func (s *userService) Update(ctx context.Context, id int, req *UpdateUserRequest) (*User, error) {
    if id <= 0 {
        return nil, ErrInvalidInput
    }
    
    if err := validate.Struct(req); err != nil {
        return nil, ErrInvalidInput
    }
    
    // 更新用户逻辑
    // user, err := s.userRepository.GetByID(ctx, id)
    // if err != nil {
    //     if errors.Is(err, ErrNotFound) {
    //         return nil, ErrNotFound
    //     }
    //     return nil, ErrInternal
    // }
    //
    // user.Name = req.Name
    // user.Email = req.Email
    // user.UpdatedAt = time.Now()
    // s.userRepository.Update(ctx, user)
    
    return &User{ID: id, Name: req.Name, Email: req.Email}, nil
}

func (s *userService) Delete(ctx context.Context, id int) error {
    if id <= 0 {
        return ErrInvalidInput
    }
    
    // 删除用户逻辑
    // if err := s.userRepository.Delete(ctx, id); err != nil {
    //     if errors.Is(err, ErrNotFound) {
    //         return ErrNotFound
    //     }
    //     return ErrInternal
    // }
    
    return nil
}

// 验证器
var validate *validator.Validate

func init() {
    if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
        validate = v
    }
}

// 中间件
func errorMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        c.Next()
        
        if len(c.Errors) > 0 {
            err := c.Errors.Last().Err
            var statusCode int
            var message string
            
            switch {
            case errors.Is(err, ErrNotFound):
                statusCode = http.StatusNotFound
                message = "Resource not found"
            case errors.Is(err, ErrInvalidInput):
                statusCode = http.StatusBadRequest
                message = "Invalid input"
            case errors.Is(err, ErrUnauthorized):
                statusCode = http.StatusUnauthorized
                message = "Unauthorized"
            default:
                statusCode = http.StatusInternalServerError
                message = "Internal server error"
                log.Printf("Internal error: %v", err)
            }
            
            c.JSON(statusCode, ErrorResponse{
                Error:   err.Error(),
                Message: message,
            })
        }
    }
}

func paginationMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        pageStr := c.DefaultQuery("page", "1")
        pageSizeStr := c.DefaultQuery("page_size", "10")
        
        page, err := strconv.Atoi(pageStr)
        if err != nil || page < 1 {
            page = 1
        }
        
        pageSize, err := strconv.Atoi(pageSizeStr)
        if err != nil || pageSize < 1 || pageSize > 100 {
            pageSize = 10
        }
        
        c.Set("page", page)
        c.Set("page_size", pageSize)
        
        c.Next()
    }
}

// 控制器
type UserController struct {
    service UserService
}

func NewUserController(service UserService) *UserController {
    return &UserController{service: service}
}

func (uc *UserController) CreateUser(c *gin.Context) {
    var req CreateUserRequest
    if err := c.ShouldBindJSON(&req); err != nil {
        c.Error(ErrInvalidInput)
        return
    }
    
    user, err := uc.service.Create(c.Request.Context(), &req)
    if err != nil {
        c.Error(err)
        return
    }
    
    c.JSON(http.StatusCreated, SuccessResponse{Data: user})
}

func (uc *UserController) GetUser(c *gin.Context) {
    id, err := strconv.Atoi(c.Param("id"))
    if err != nil {
        c.Error(ErrInvalidInput)
        return
    }
    
    user, err := uc.service.GetByID(c.Request.Context(), id)
    if err != nil {
        c.Error(err)
        return
    }
    
    c.JSON(http.StatusOK, SuccessResponse{Data: user})
}

func (uc *UserController) GetUsers(c *gin.Context) {
    page, _ := c.Get("page")
    pageSize, _ := c.Get("page_size")
    
    users, meta, err := uc.service.GetAll(c.Request.Context(), page.(int), pageSize.(int))
    if err != nil {
        c.Error(err)
        return
    }
    
    c.JSON(http.StatusOK, SuccessResponse{Data: users, Meta: meta})
}

func (uc *UserController) UpdateUser(c *gin.Context) {
    id, err := strconv.Atoi(c.Param("id"))
    if err != nil {
        c.Error(ErrInvalidInput)
        return
    }
    
    var req UpdateUserRequest
    if err := c.ShouldBindJSON(&req); err != nil {
        c.Error(ErrInvalidInput)
        return
    }
    
    user, err := uc.service.Update(c.Request.Context(), id, &req)
    if err != nil {
        c.Error(err)
        return
    }
    
    c.JSON(http.StatusOK, SuccessResponse{Data: user})
}

func (uc *UserController) DeleteUser(c *gin.Context) {
    id, err := strconv.Atoi(c.Param("id"))
    if err != nil {
        c.Error(ErrInvalidInput)
        return
    }
    
    err = uc.service.Delete(c.Request.Context(), id)
    if err != nil {
        c.Error(err)
        return
    }
    
    c.JSON(http.StatusNoContent, nil)
}

func main() {
    r := gin.Default()
    
    // 注册中间件
    r.Use(errorMiddleware())
    r.Use(gin.Logger())
    r.Use(gin.Recovery())
    
    // 创建服务和控制器
    service := &userService{}
    userController := NewUserController(service)
    
    // 路由
    api := r.Group("/api/v1")
    {
        api.GET("/health", func(c *gin.Context) {
            c.JSON(http.StatusOK, gin.H{"status": "ok", "version": "1.0.0"})
        })
        
        users := api.Group("/users")
        users.Use(paginationMiddleware())
        {
            users.POST("", userController.CreateUser)
            users.GET("", userController.GetUsers)
            users.GET("/:id", userController.GetUser)
            users.PUT("/:id", userController.UpdateUser)
            users.DELETE("/: id", userController.DeleteUser)
        }
    }
    
    r.Run(":8080")
}

第十一章:实际应用场景

11.1 CLI工具开发

// cli.go
package main

import (
    "fmt"
    "os"
    
    "github.com/spf13/cobra"
)

var (
    cfgFile string
    verbose bool
)

func main() {
    rootCmd := &cobra.Command{
        Use:   "mycli",
        Short: "A brief description of your application",
        Long: `A longer description that spans multiple lines and likely contains
examples and usage of using your application.`,
        Run: func(cmd *cobra.Command, args []string) {
            if verbose {
                fmt.Println("Verbose mode enabled")
            }
            fmt.Println("Welcome to mycli!")
        },
    }
    
    rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.mycli.yaml)")
    rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose output")
    
    // 子命令
    var name string
    greetCmd := &cobra.Command{
        Use:   "greet",
        Short: "Greet someone",
        Long:  `Greet someone by name`,
        Args:  cobra.ExactArgs(1),
        Run: func(cmd *cobra.Command, args []string) {
            name = args[0]
            if verbose {
                fmt.Printf("Greeting %s\n", name)
            }
            fmt.Printf("Hello, %s!\n", name)
        },
    }
    
    rootCmd.AddCommand(greetCmd)
    
    // 文件操作子命令
    fileCmd := &cobra.Command{
        Use:   "file",
        Short: "File operations",
        Long:  `Operations on files`,
    }
    
    createCmd := &cobra.Command{
        Use:   "create [filename]",
        Short: "Create a file",
        Args:  cobra.ExactArgs(1),
        Run: func(cmd *cobra.Command, args []string) {
            filename := args[0]
            if err := os.WriteFile(filename, []byte("Hello, World!"), 0644); err != nil {
                fmt.Printf("Error creating file: %v\n", err)
                os.Exit(1)
            }
            fmt.Printf("Created file: %s\n", filename)
        },
    }
    
    fileCmd.AddCommand(createCmd)
    rootCmd.AddCommand(fileCmd)
    
    if err := rootCmd.Execute(); err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
}

11.2 微服务架构

// microservice.go
package main

import (
    "context"
    "encoding/json"
    "log"
    "net/http"
    "time"
    
    "github.com/redis/go-redis/v9"
    "github.com/streadway/amqp"
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/exporters/jaeger"
    "go.opentelemetry.io/otel/sdk/resource"
    sdktrace "go.opentelemetry.io/otel/sdk/trace"
    semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
)

// 消息结构
type OrderCreatedEvent struct {
    OrderID    string    `json:"order_id"`
    CustomerID string    `json:"customer_id"`
    Amount     float64   `json:"amount"`
    CreatedAt  time.Time `json:"created_at"`
}

type InventoryService struct {
    redisClient *redis.Client
    amqpChannel *amqp.Channel
    tracer      trace.Tracer
}

func NewInventoryService(redisAddr, amqpURL string) (*InventoryService, error) {
    // Redis连接
    redisClient := redis.NewClient(&redis.Options{
        Addr: redisAddr,
        DB:   0,
    })
    
    // AMQP连接
    conn, err := amqp.Dial(amqpURL)
    if err != nil {
        return nil, err
    }
    channel, err := conn.Channel()
    if err != nil {
        return nil, err
    }
    
    // OpenTelemetry配置
    exporter, err := jaeger.New(jaeger.WithCollectorEndpoint())
    if err != nil {
        return nil, err
    }
    
    tp := sdktrace.NewTracerProvider(
        sdktrace.WithBatcher(exporter),
        sdktrace.WithResource(resource.NewWithAttributes(
            semconv.SchemaURL,
            semconv.ServiceNameKey.String("inventory-service"),
        )),
    )
    
    otel.SetTracerProvider(tp)
    tracer := otel.Tracer("inventory-service")
    
    return &InventoryService{
        redisClient: redisClient,
        amqpChannel: channel,
        tracer:      tracer,
    }, nil
}

func (s *InventoryService) ReserveStock(ctx context.Context, productID string, quantity int) error {
    ctx, span := s.tracer.Start(ctx, "ReserveStock")
    defer span.End()
    
    key := "stock:" + productID
    current, err := s.redisClient.Get(ctx, key).Int()
    if err != nil && err != redis.Nil {
        return err
    }
    
    if current < quantity {
        return fmt.Errorf("insufficient stock for product %s", productID)
    }
    
    _, err = s.redisClient.DecrBy(ctx, key, int64(quantity)).Result()
    return err
}

func (s *InventoryService) ProcessOrderCreated(ctx context.Context, event *OrderCreatedEvent) error {
    ctx, span := s.tracer.Start(ctx, "ProcessOrderCreated")
    defer span.End()
    
    // 解析订单项(简化)
    productID := "product-123" // 从事件中获取
    quantity := 1              // 从事件中获取
    
    if err := s.ReserveStock(ctx, productID, quantity); err != nil {
        // 发布库存不足事件
        insufficientEvent := map[string]interface{}{
            "order_id": event.OrderID,
            "reason":   err.Error(),
        }
        
        body, _ := json.Marshal(insufficientEvent)
        s.amqpChannel.Publish(
            "",
            "inventory.insufficient",
            false,
            false,
            amqp.Publishing{
                ContentType: "application/json",
                Body:        body,
            },
        )
        
        return err
    }
    
    // 发布库存预留成功事件
    reservedEvent := map[string]interface{}{
        "order_id":   event.OrderID,
        "product_id": productID,
        "quantity":   quantity,
    }
    
    body, _ := json.Marshal(reservedEvent)
    s.amqpChannel.Publish(
            "",
            "inventory.reserved",
            false,
            false,
            amqp.Publishing{
                ContentType: "application/json",
                Body:        body,
            },
        )
    
    return nil
}

func (s *InventoryService) StartMessageConsumer(ctx context.Context) error {
    q, err := s.amqpChannel.QueueDeclare(
        "order.created",
        true,
        false,
        false,
        false,
        nil,
    )
    if err != nil {
        return err
    }
    
    s.amqpChannel.QueueBind(
        q.Name,
        "order.created",
        "events",
        false,
        nil,
    )
    
    msgs, err := s.amqpChannel.Consume(
        q.Name,
        "",
        true,
        false,
        false,
        false,
        nil,
    )
    if err != != nil {
        return err
    }
    
    go func() {
        for msg := range msgs {
            var event OrderCreatedEvent
            if err := json.Unmarshal(msg.Body, &event); err != nil {
                log.Printf("Failed to unmarshal message: %v", err)
                continue
            }
            
            if err := s.ProcessOrderCreated(ctx, &event); err != nil {
                log.Printf("Failed to process order created event: %v", err)
            }
        }
    }()
    
    return nil
}

func (s *InventoryService) HealthCheck(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("OK"))
}

func main() {
    ctx := context.Background()
    
    service, err := NewInventoryService("localhost:6379", "amqp://guest:guest@localhost:5672/")
    if err != nil {
        log.Fatal("Failed to create inventory service:", err)
    }
    
    // 启动消息消费者
    if err := service.StartMessageConsumer(ctx); err != nil {
        log.Fatal("Failed to start message consumer:", err)
    }
    
    // HTTP服务器
    http.HandleFunc("/health", service.HealthCheck)
    
    log.Println("Inventory service starting on :8081")
    log.Fatal(http.ListenAndServe(":8081", nil))
}

11.3 数据处理管道

// pipeline.go
package main

import (
    "bufio"
    "context"
    "encoding/csv"
    "fmt"
    "os"
    "strconv"
    "sync"
    "time"
)

// 数据模型
type Record struct {
    ID    int
    Name  string
    Value float64
}

// 管道阶段
func readFile(ctx context.Context, filename string) (<-chan string, <-chan error) {
    out := make(chan string)
    errs := make(chan error, 1)
    
    go func() {
        defer close(out)
        defer close(errs)
        
        file, err := os.Open(filename)
        if err != nil {
            errs <- err
            return
        }
        defer file.Close()
        
        scanner := bufio.NewScanner(file)
        for scanner.Scan() {
            select {
            case out <- scanner.Text():
            case <-ctx.Done():
                return
            }
        }
        
        if err := scanner.Err(); err != nil {
            errs <- err
        }
    }()
    
    return out, errs
}

func parseCSV(ctx context.Context, lines <-chan string) (<-chan []string, <-chan error) {
    out := make(chan []string)
    errs := make(chan error, 1)
    
    go func() {
        defer close(out)
        defer close(errs)
        
        reader := csv.NewReader(nil)
        for line := range lines {
            reader.Reset(strings.NewReader(line))
            record, err := reader.Read()
            if err != nil {
                errs <- err
                return
            }
            
            select {
            case out <- record:
            case <-ctx.Done():
                return
            }
        }
    }()
    
    return out, errs
}

func transformRecords(ctx context.Context, records <-chan []string) (<-chan Record, <-chan error) {
    out := make(chan Record)
    errs := make(chan error, 1)
    
    go func() {
        defer close(out)
        defer close(errs)
        
        for record := range records {
            if len(record) < 3 {
                errs <- fmt.Errorf("invalid record: %v", record)
                return
            }
            
            id, err := strconv.Atoi(record[0])
            if err != nil {
                errs <- fmt.Errorf("invalid ID: %s", record[0])
                return
            }
            
            value, err := strconv.ParseFloat(record[2], 64)
            if err != nil {
                errs <- fmt.Errorf("invalid value: %s", record[2])
                return
            }
            
            transformed := Record{
                ID:    id,
                Name:  record[1],
                Value: value,
            }
            
            select {
            case out <- transformed:
            case <-ctx.Done():
                return
            }
        }
    }()
    
    return out, errs
}

func processRecords(ctx context.Context, records <-chan Record, batchSize int) (<-chan []Record, <-chan error) {
    out := make(chan []Record)
    errs := make(chan error, 1)
    
    go func() {
        defer close(out)
        defer close(errs)
        
        var batch []Record
        ticker := time.NewTicker(1 * time.Second)
        defer ticker.Stop()
        
        for {
            select {
            case record, ok := <-records:
                if !ok {
                    // 输入通道关闭,发送剩余批次
                    if len(batch) > 0 {
                        out <- batch
                    }
                    return
                }
                
                batch = append(batch, record)
                if len(batch) >= batchSize {
                    out <- batch
                    batch = nil
                }
                
            case <-ticker.C:
                // 定时发送批次
                if len(batch) > 0 {
                    out <- batch
                    batch = nil
                }
                
            case <-ctx.Done():
                return
            }
        }
    }()
    
    return out, errs
}

func saveToDatabase(ctx context.Context, batches <-chan []Record) <-chan error {
    errs := make(chan error, 1)
    
    go func() {
        defer close(errs)
        
        for batch := range batches {
            // 模拟数据库保存
            time.Sleep(100 * time.Millisecond)
            fmt.Printf("Saved batch of %d records\n", len(batch))
        }
    }()
    
    return errs
}

func runPipeline(ctx context.Context, filename string) error {
    lines, lineErrs := readFile(ctx, filename)
    records, recordErrs := parseCSV(ctx, lines)
    transformed, transformErrs := transformRecords(ctx, records)
    batches, batchErrs := processRecords(ctx, transformed, 10)
    saveErrs := saveToDatabase(ctx, batches)
    
    // 错误处理
    var wg sync.WaitGroup
    errChan := make(chan error, 5)
    
    collectErrors := func(errs <-chan error) {
        defer wg.Done()
        for err := range errs {
            errChan <- err
        }
    }
    
    wg.Add(5)
    go collectErrors(lineErrs)
    go collectErrors(recordErrs)
    go collectErrors(transformErrs)
    go collectErrors(batchErrs)
    go collectErrors(saveErrs)
    
    // 等待完成或错误
    go func() {
        wg.Wait()
        close(errChan)
    }()
    
    select {
    case err := <-errChan:
        if err != nil {
            return err
        }
    case <-ctx.Done():
        return ctx.Err()
    }
    
    return nil
}

func main() {
    // 创建示例CSV文件
    sampleData := `1,Alice,100.5
2,Bob,200.75
3,Carol,150.25
4,David,300.0
5,Eve,175.8`
    
    os.WriteFile("sample.csv", []byte(sampleData), 0644)
    
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    
    if err := runPipeline(ctx, "sample.csv"); err != nil {
        fmt.Printf("Pipeline failed: %v\n", err)
    } else {
        fmt.Println("Pipeline completed successfully")
    }
}

总结

Go语言作为一门现代化的系统编程语言,在2026年继续保持着其在云原生、微服务和高性能应用领域的领先地位。通过本文的学习,你应该已经掌握了:

  1. 基础语法:变量、数据类型、控制结构、函数
  2. 复合类型:数组、切片、map、结构体
  3. 面向对象:方法、接口、组合优于继承
  4. 泛型编程:类型参数、约束、泛型数据结构
  5. 并发模型:goroutine、channel、同步原语、并发模式
  6. 错误处理:多返回值、错误包装、自定义错误
  7. 包管理:Go modules、依赖管理、工作区
  8. 测试:单元测试、基准测试、模拟、覆盖率
  9. Web开发:HTTP服务器、REST API、数据库操作
  10. 实际应用:CLI工具、微服务、数据处理管道

学习建议

  • 从简单的命令行程序开始,逐步构建Web服务
  • 阅读优秀的Go代码,如标准库和知名开源项目
  • 遵循Go的惯用法和最佳实践
  • 关注Go社区的最新动态和发展趋势
  • 在实际项目中不断练习和应用所学知识

Go的学习是一个持续的过程,随着你对语言特性和最佳实践的深入理解,你会发现更多高级功能和应用场景。希望这篇指南能够为你打下坚实的基础,助你在Go开发的道路上越走越远!

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐