Go语言入门到精通【全集】

Go语言入门到精通教程

目录

  1. Go语言简介
  2. 环境搭建
  3. 基础语法
  4. 数据类型
  5. 控制结构
  6. 函数
  7. 数组和切片
  8. Map映射
  9. 结构体
  10. 方法和接口
  11. 并发编程
  12. 错误处理
  13. 包管理
  14. 文件操作
  15. 网络编程
  16. 数据库操作
  17. 测试
  18. 性能优化
  19. 实战项目
  20. 进阶主题

1. Go语言简介

1.1 什么是Go语言

Go(又称Golang)是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。

特点:

  • 简洁、快速、安全
  • 并行、有趣、开源
  • 内存管理、数组安全、编译迅速

1.2 Go语言的优势

  1. 简单易学:语法简洁,关键字少(25个)
  2. 高性能:接近C语言的性能
  3. 并发支持:原生支持并发编程(goroutine)
  4. 快速编译:编译速度极快
  5. 跨平台:支持多平台交叉编译
  6. 丰富的标准库:功能强大的标准库
  7. 垃圾回收:自动内存管理

1.3 Go语言应用场景

  • 服务器编程
  • 分布式系统
  • 网络编程
  • 云计算
  • 容器技术(Docker、Kubernetes)
  • 区块链
  • 微服务

2. 环境搭建

2.1 安装Go

Windows安装
# 1. 下载安装包
# 访问 https://golang.org/dl/ 下载Windows安装包

# 2. 运行安装程序,默认安装到 C:\Go

# 3. 验证安装
go version
Linux安装
# 1. 下载
wget https://golang.org/dl/go1.21.5.linux-amd64.tar.gz

# 2. 解压
sudo tar -C /usr/local -xzf go1.21.5.linux-amd64.tar.gz

# 3. 配置环境变量
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
source ~/.bashrc

# 4. 验证
go version
macOS安装
# 使用Homebrew
brew install go

# 验证
go version

2.2 配置环境变量

# GOROOT:Go安装目录
export GOROOT=/usr/local/go

# GOPATH:工作目录
export GOPATH=$HOME/go

# PATH:添加Go二进制文件路径
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin

# GOPROXY:配置代理(中国用户推荐)
export GOPROXY=https://goproxy.cn,direct

2.3 IDE选择

推荐IDE:

  1. Visual Studio Code + Go插件
  2. GoLand(JetBrains出品)
  3. Vim/Neovim + vim-go
  4. Sublime Text + GoSublime

2.4 第一个Go程序

// hello.go
package main

import "fmt"

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

运行程序:

# 方式1:直接运行
go run hello.go

# 方式2:编译后运行
go build hello.go
./hello

# 方式3:安装到GOPATH/bin
go install hello.go

3. 基础语法

3.1 包声明

package main  // 声明包名,main包是程序入口

3.2 导入包

// 单个导入
import "fmt"

// 多个导入
import (
    "fmt"
    "math"
    "strings"
)

// 别名导入
import (
    f "fmt"
    m "math"
)

// 点导入(不推荐)
import . "fmt"

// 匿名导入(只执行init函数)
import _ "database/sql"

3.3 变量声明

package main

import "fmt"

func main() {
    // 方式1:标准声明
    var name string = "Go"
    
    // 方式2:类型推断
    var age = 10
    
    // 方式3:短变量声明(只能在函数内使用)
    version := 1.21
    
    // 方式4:批量声明
    var (
        a int = 1
        b string = "hello"
        c bool = true
    )
    
    // 方式5:多变量声明
    var x, y, z int = 1, 2, 3
    m, n := 100, 200
    
    fmt.Println(name, age, version, a, b, c, x, y, z, m, n)
}

3.4 常量

package main

import "fmt"

func main() {
    // 普通常量
    const PI = 3.14159
    const URL = "https://golang.org"
    
    // 批量声明
    const (
        StatusOK = 200
        StatusNotFound = 404
        StatusError = 500
    )
    
    // iota枚举
    const (
        Sunday = iota    // 0
        Monday           // 1
        Tuesday          // 2
        Wednesday        // 3
        Thursday         // 4
        Friday           // 5
        Saturday         // 6
    )
    
    // iota高级用法
    const (
        _  = iota             // 0,使用_忽略
        KB = 1 << (10 * iota) // 1 << 10 = 1024
        MB                     // 1 << 20 = 1048576
        GB                     // 1 << 30
        TB                     // 1 << 40
    )
    
    fmt.Println(PI, StatusOK, Monday, KB, MB)
}

3.5 注释

// 单行注释

/*
多行注释
可以跨越多行
*/

// 文档注释(用于生成文档)
// Package main 提供程序入口
package main

// Add 函数用于计算两个整数的和
func Add(a, b int) int {
    return a + b
}

4. 数据类型

4.1 基本数据类型

4.1.1 布尔类型
var flag bool = true
var isValid bool = false

// 布尔运算
result := true && false  // false
result = true || false   // true
result = !true           // false
4.1.2 数字类型
// 整数类型
var i8 int8 = 127           // -128 到 127
var i16 int16 = 32767       // -32768 到 32767
var i32 int32 = 2147483647  // -2^31 到 2^31-1
var i64 int64 = 9223372036854775807

var ui8 uint8 = 255         // 0 到 255
var ui16 uint16 = 65535     // 0 到 65535
var ui32 uint32 = 4294967295
var ui64 uint64 = 18446744073709551615

// int和uint:根据平台自动选择32位或64位
var i int = 100
var ui uint = 200

// 特殊整数类型
var b byte = 255      // uint8的别名
var r rune = '中'     // int32的别名,表示Unicode码点

// 浮点类型
var f32 float32 = 3.14
var f64 float64 = 3.141592653589793

// 复数类型
var c64 complex64 = 1 + 2i
var c128 complex128 = 2 + 3i
4.1.3 字符串类型
package main

import (
    "fmt"
    "strings"
)

func main() {
    // 字符串声明
    var s1 string = "Hello"
    s2 := "World"
    
    // 多行字符串
    s3 := `这是一个
多行字符串
可以包含换行`
    
    // 字符串连接
    s4 := s1 + " " + s2
    s5 := fmt.Sprintf("%s %s", s1, s2)
    
    // 字符串长度
    length := len(s1)  // 字节长度
    
    // 字符串遍历
    for i := 0; i < len(s1); i++ {
        fmt.Printf("%c ", s1[i])  // 按字节遍历
    }
    
    for _, r := range s1 {
        fmt.Printf("%c ", r)  // 按字符遍历
    }
    
    // 字符串操作
    contains := strings.Contains(s1, "He")     // 包含
    hasPrefix := strings.HasPrefix(s1, "He")   // 前缀
    hasSuffix := strings.HasSuffix(s1, "lo")   // 后缀
    index := strings.Index(s1, "ll")           // 查找
    replace := strings.Replace(s1, "l", "L", -1) // 替换
    split := strings.Split(s1, "l")            // 分割
    upper := strings.ToUpper(s1)               // 转大写
    lower := strings.ToLower(s1)               // 转小写
    
    fmt.Println(s4, s5, length, contains, hasPrefix, hasSuffix, 
                index, replace, split, upper, lower)
}

4.2 复合数据类型

4.2.1 指针
package main

import "fmt"

func main() {
    // 声明指针
    var p *int
    
    // 获取变量地址
    var a int = 10
    p = &a
    
    // 解引用
    fmt.Println(*p)  // 10
    
    // 修改指针指向的值
    *p = 20
    fmt.Println(a)   // 20
    
    // new函数创建指针
    ptr := new(int)
    *ptr = 100
    fmt.Println(*ptr)
    
    // 指针作为函数参数
    swap(&a, ptr)
}

func swap(x, y *int) {
    temp := *x
    *x = *y
    *y = temp
}
4.2.2 类型转换
package main

import (
    "fmt"
    "strconv"
)

func main() {
    // 数值类型转换
    var i int = 42
    var f float64 = float64(i)
    var u uint = uint(f)
    
    // 字符串转换
    // 整数转字符串
    str1 := strconv.Itoa(i)
    str2 := fmt.Sprintf("%d", i)
    
    // 字符串转整数
    num1, err := strconv.Atoi("123")
    num2, err := strconv.ParseInt("123", 10, 64)
    
    // 浮点数转字符串
    str3 := strconv.FormatFloat(3.14, 'f', 2, 64)
    
    // 字符串转浮点数
    f1, err := strconv.ParseFloat("3.14", 64)
    
    // 布尔转换
    str4 := strconv.FormatBool(true)
    b1, err := strconv.ParseBool("true")
    
    fmt.Println(f, u, str1, str2, num1, num2, str3, f1, str4, b1, err)
}

5. 控制结构

5.1 条件语句

5.1.1 if语句
package main

import "fmt"

func main() {
    // 基本if
    x := 10
    if x > 5 {
        fmt.Println("x大于5")
    }
    
    // if-else
    if x > 15 {
        fmt.Println("x大于15")
    } else {
        fmt.Println("x不大于15")
    }
    
    // if-else if-else
    if x > 15 {
        fmt.Println("x大于15")
    } else if x > 10 {
        fmt.Println("x大于10")
    } else {
        fmt.Println("x不大于10")
    }
    
    // if简短语句
    if y := x * 2; y > 15 {
        fmt.Println("y大于15")
    }
}
5.1.2 switch语句
package main

import (
    "fmt"
    "time"
)

func main() {
    // 基本switch
    day := 3
    switch day {
    case 1:
        fmt.Println("Monday")
    case 2:
        fmt.Println("Tuesday")
    case 3:
        fmt.Println("Wednesday")
    default:
        fmt.Println("Other day")
    }
    
    // 多条件switch
    switch day {
    case 1, 2, 3, 4, 5:
        fmt.Println("Weekday")
    case 6, 7:
        fmt.Println("Weekend")
    }
    
    // 无条件switch(相当于if-else链)
    score := 85
    switch {
    case score >= 90:
        fmt.Println("A")
    case score >= 80:
        fmt.Println("B")
    case score >= 70:
        fmt.Println("C")
    default:
        fmt.Println("D")
    }
    
    // switch类型判断
    var i interface{} = "hello"
    switch v := i.(type) {
    case int:
        fmt.Printf("整数: %d\n", v)
    case string:
        fmt.Printf("字符串: %s\n", v)
    case bool:
        fmt.Printf("布尔: %t\n", v)
    default:
        fmt.Printf("未知类型: %T\n", v)
    }
    
    // fallthrough关键字
    switch time.Now().Weekday() {
    case time.Saturday:
        fmt.Println("Today is Saturday")
        fallthrough
    case time.Sunday:
        fmt.Println("Today is weekend")
    }
}

5.2 循环语句

package main

import "fmt"

func main() {
    // 基本for循环
    for i := 0; i < 5; i++ {
        fmt.Println(i)
    }
    
    // while风格的for循环
    j := 0
    for j < 5 {
        fmt.Println(j)
        j++
    }
    
    // 无限循环
    k := 0
    for {
        if k >= 5 {
            break
        }
        fmt.Println(k)
        k++
    }
    
    // for range遍历
    // 遍历数组/切片
    nums := []int{1, 2, 3, 4, 5}
    for index, value := range nums {
        fmt.Printf("索引: %d, 值: %d\n", index, value)
    }
    
    // 只要索引
    for index := range nums {
        fmt.Println(index)
    }
    
    // 只要值
    for _, value := range nums {
        fmt.Println(value)
    }
    
    // 遍历字符串
    str := "Hello"
    for index, char := range str {
        fmt.Printf("%d: %c\n", index, char)
    }
    
    // 遍历map
    m := map[string]int{"a": 1, "b": 2, "c": 3}
    for key, value := range m {
        fmt.Printf("%s: %d\n", key, value)
    }
    
    // break和continue
    for i := 0; i < 10; i++ {
        if i == 3 {
            continue  // 跳过本次循环
        }
        if i == 7 {
            break     // 跳出循环
        }
        fmt.Println(i)
    }
    
    // 标签跳转
OuterLoop:
    for i := 0; i < 3; i++ {
        for j := 0; j < 3; j++ {
            if i == 1 && j == 1 {
                break OuterLoop  // 跳出外层循环
            }
            fmt.Printf("i=%d, j=%d\n", i, j)
        }
    }
}

5.3 goto语句

package main

import "fmt"

func main() {
    i := 0
Loop:
    if i < 5 {
        fmt.Println(i)
        i++
        goto Loop
    }
    
    // goto用于错误处理
    err := doSomething()
    if err != nil {
        goto ErrorHandler
    }
    
    fmt.Println("Success")
    return
    
ErrorHandler:
    fmt.Println("Error occurred")
}

func doSomething() error {
    return nil
}

6. 函数

6.1 函数定义

package main

import "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, fmt.Errorf("除数不能为0")
    }
    return a / b, nil
}

// 命名返回值
func calculate(a, b int) (sum int, product int) {
    sum = a + b
    product = a * b
    return  // 直接return,返回命名的变量
}

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

func main() {
    // 调用函数
    result1 := add(3, 5)
    result2 := multiply(4, 6)
    
    result3, err := divide(10, 2)
    if err != nil {
        fmt.Println(err)
    }
    
    s, p := calculate(3, 4)
    
    total := sum(1, 2, 3, 4, 5)
    
    fmt.Println(result1, result2, result3, s, p, total)
}

6.2 函数高级特性

package main

import "fmt"

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

// 函数作为返回值
func getOperation(op string) func(int, int) int {
    switch op {
    case "+":
        return func(a, b int) int { return a + b }
    case "-":
        return func(a, b int) int { return a - b }
    case "*":
        return func(a, b int) int { return a * b }
    default:
        return nil
    }
}

// 闭包
func counter() func() int {
    count := 0
    return func() int {
        count++
        return count
    }
}

// 递归函数
func factorial(n int) int {
    if n <= 1 {
        return 1
    }
    return n * factorial(n-1)
}

// 匿名函数
func main() {
    // 使用函数作为参数
    result := apply(func(a, b int) int {
        return a + b
    }, 3, 5)
    
    // 使用函数作为返回值
    addFunc := getOperation("+")
    sum := addFunc(10, 20)
    
    // 使用闭包
    c := counter()
    fmt.Println(c())  // 1
    fmt.Println(c())  // 2
    fmt.Println(c())  // 3
    
    // 递归
    fact := factorial(5)  // 120
    
    // 匿名函数立即执行
    func(msg string) {
        fmt.Println(msg)
    }("Hello from anonymous function")
    
    fmt.Println(result, sum, fact)
}

6.3 defer语句

package main

import (
    "fmt"
    "os"
)

func main() {
    // defer基本用法(后进先出)
    defer fmt.Println("1")
    defer fmt.Println("2")
    defer fmt.Println("3")
    fmt.Println("4")
    // 输出: 4 3 2 1
    
    // defer用于资源清理
    file, err := os.Open("test.txt")
    if err != nil {
        return
    }
    defer file.Close()  // 确保文件被关闭
    
    // defer参数立即求值
    x := 10
    defer fmt.Println(x)  // 输出10
    x = 20
    
    // defer与panic/recover
    deferPanicRecover()
}

func deferPanicRecover() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered from:", r)
        }
    }()
    
    panic("Something went wrong!")
}

6.4 init函数

package main

import "fmt"

// init函数在main之前自动执行
// 一个包可以有多个init函数
func init() {
    fmt.Println("Init 1")
}

func init() {
    fmt.Println("Init 2")
}

func main() {
    fmt.Println("Main")
}
// 输出: Init 1, Init 2, Main

7. 数组和切片

7.1 数组

package main

import "fmt"

func main() {
    // 数组声明
    var arr1 [5]int  // 声明长度为5的整数数组
    
    // 数组初始化
    var arr2 = [5]int{1, 2, 3, 4, 5}
    arr3 := [5]int{1, 2, 3, 4, 5}
    arr4 := [...]int{1, 2, 3, 4, 5}  // 自动推断长度
    arr5 := [5]int{0: 1, 2: 3, 4: 5}  // 指定索引初始化
    
    // 访问数组元素
    fmt.Println(arr2[0])  // 1
    arr2[0] = 10
    
    // 数组长度
    length := len(arr2)
    
    // 遍历数组
    for i := 0; i < len(arr2); i++ {
        fmt.Println(arr2[i])
    }
    
    for index, value := range arr2 {
        fmt.Printf("索引: %d, 值: %d\n", index, value)
    }
    
    // 多维数组
    var matrix [3][4]int
    matrix2 := [2][3]int{
        {1, 2, 3},
        {4, 5, 6},
    }
    
    // 数组是值类型
    arr6 := [3]int{1, 2, 3}
    arr7 := arr6  // 复制整个数组
    arr7[0] = 100
    fmt.Println(arr6[0])  // 1(不受影响)
    
    fmt.Println(arr1, arr3, arr4, arr5, length, matrix, matrix2)
}

7.2 切片

package main

import "fmt"

func main() {
    // 切片声明
    var slice1 []int  // 声明切片,初始值为nil
    
    // 使用make创建切片
    slice2 := make([]int, 5)       // 长度和容量都是5
    slice3 := make([]int, 5, 10)   // 长度5,容量10
    
    // 切片字面量
    slice4 := []int{1, 2, 3, 4, 5}
    
    // 从数组创建切片
    arr := [5]int{1, 2, 3, 4, 5}
    slice5 := arr[1:4]  // [2, 3, 4]
    slice6 := arr[:3]   // [1, 2, 3]
    slice7 := arr[2:]   // [3, 4, 5]
    slice8 := arr[:]    // [1, 2, 3, 4, 5]
    
    // 切片长度和容量
    fmt.Printf("长度: %d, 容量: %d\n", len(slice4), cap(slice4))
    
    // 追加元素
    slice4 = append(slice4, 6)
    slice4 = append(slice4, 7, 8, 9)
    slice4 = append(slice4, []int{10, 11, 12}...)
    
    // 复制切片
    slice9 := make([]int, len(slice4))
    copy(slice9, slice4)
    
    // 删除元素
    // 删除索引为2的元素
    index := 2
    slice4 = append(slice4[:index], slice4[index+1:]...)
    
    // 插入元素
    // 在索引2处插入100
    slice4 = append(slice4[:index], append([]int{100}, slice4[index:]...)...)
    
    // 遍历切片
    for i, v := range slice4 {
        fmt.Printf("索引: %d, 值: %d\n", i, v)
    }
    
    // 切片是引用类型
    slice10 := []int{1, 2, 3}
    slice11 := slice10
    slice11[0] = 100
    fmt.Println(slice10[0])  // 100(受影响)
    
    fmt.Println(slice1, slice2, slice3, slice5, slice6, slice7, slice8, slice9)
}

7.3 切片高级操作

package main

import (
    "fmt"
    "sort"
)

func main() {
    // 二维切片
    matrix := [][]int{
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9},
    }
    
    // 动态创建二维切片
    rows, cols := 3, 4
    matrix2 := make([][]int, rows)
    for i := range matrix2 {
        matrix2[i] = make([]int, cols)
    }
    
    // 切片排序
    nums := []int{5, 2, 8, 1, 9, 3}
    sort.Ints(nums)  // 升序
    fmt.Println(nums)
    
    sort.Sort(sort.Reverse(sort.IntSlice(nums)))  // 降序
    fmt.Println(nums)
    
    // 切片过滤
    numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    evens := filter(numbers, func(n int) bool {
        return n%2 == 0
    })
    fmt.Println(evens)  // [2, 4, 6, 8, 10]
    
    // 切片映射
    squared := mapSlice(numbers, func(n int) int {
        return n * n
    })
    fmt.Println(squared)
    
    fmt.Println(matrix, matrix2)
}

// 过滤函数
func filter(slice []int, f func(int) bool) []int {
    result := make([]int, 0)
    for _, v := range slice {
        if f(v) {
            result = append(result, v)
        }
    }
    return result
}

// 映射函数
func mapSlice(slice []int, f func(int) int) []int {
    result := make([]int, len(slice))
    for i, v := range slice {
        result[i] = f(v)
    }
    return result
}

8. Map映射

8.1 Map基础

package main

import "fmt"

func main() {
    // Map声明
    var map1 map[string]int  // 声明但未初始化,值为nil
    
    // 使用make创建Map
    map2 := make(map[string]int)
    map3 := make(map[string]int, 10)  // 指定初始容量
    
    // Map字面量
    map4 := map[string]int{
        "apple":  1,
        "banana": 2,
        "orange": 3,
    }
    
    // 添加/修改元素
    map2["key1"] = 100
    map2["key2"] = 200
    
    // 获取元素
    value := map2["key1"]
    
    // 检查键是否存在
    value, ok := map2["key3"]
    if ok {
        fmt.Println("存在:", value)
    } else {
        fmt.Println("不存在")
    }
    
    // 删除元素
    delete(map2, "key1")
    
    // 遍历Map
    for key, value := range map4 {
        fmt.Printf("%s: %d\n", key, value)
    }
    
    // 只遍历键
    for key := range map4 {
        fmt.Println(key)
    }
    
    // Map长度
    length := len(map4)
    
    fmt.Println(map1, map3, length)
}

8.2 Map高级操作

package main

import (
    "fmt"
    "sync"
)

func main() {
    // 嵌套Map
    users := map[string]map[string]string{
        "user1": {
            "name":  "Alice",
            "email": "alice@example.com",
        },
        "user2": {
            "name":  "Bob",
            "email": "bob@example.com",
        },
    }
    
    // 访问嵌套Map
    fmt.Println(users["user1"]["name"])
    
    // Map作为集合(Set)
    set := make(map[string]bool)
    set["item1"] = true
    set["item2"] = true
    
    // 检查元素是否在集合中
    if set["item1"] {
        fmt.Println("item1在集合中")
    }
    
    // 并发安全的Map(sync.Map)
    var syncMap sync.Map
    
    // 存储
    syncMap.Store("key1", "value1")
    syncMap.Store("key2", "value2")
    
    // 读取
    value, ok := syncMap.Load("key1")
    if ok {
        fmt.Println(value)
    }
    
    // 删除
    syncMap.Delete("key1")
    
    // 遍历
    syncMap.Range(func(key, value interface{}) bool {
        fmt.Printf("%v: %v\n", key, value)
        return true  // 返回false停止遍历
    })
}

9. 结构体

9.1 结构体定义

package main

import "fmt"

// 定义结构体
type Person struct {
    Name string
    Age  int
    Email string
}

// 匿名字段
type Student struct {
    Person  // 嵌入Person结构体
    School string
    Grade  int
}

// 空结构体
type Empty struct{}

func main() {
    // 创建结构体实例
    // 方式1:字段名初始化
    p1 := Person{
        Name:  "Alice",
        Age:   25,
        Email: "alice@example.com",
    }
    
    // 方式2:按顺序初始化
    p2 := Person{"Bob", 30, "bob@example.com"}
    
    // 方式3:部分初始化
    p3 := Person{Name: "Charlie"}
    
    // 方式4:使用new
    p4 := new(Person)
    p4.Name = "David"
    
    // 访问字段
    fmt.Println(p1.Name)
    p1.Age = 26
    
    // 匿名字段
    s := Student{
        Person: Person{Name: "Eve", Age: 20},
        School: "MIT",
        Grade:  3,
    }
    
    // 可以直接访问嵌入结构体的字段
    fmt.Println(s.Name)  // 等同于 s.Person.Name
    
    // 结构体指针
    p5 := &Person{Name: "Frank", Age: 35}
    fmt.Println(p5.Name)  // Go自动解引用
    
    // 结构体比较
    p6 := Person{Name: "Alice", Age: 25}
    p7 := Person{Name: "Alice", Age: 25}
    fmt.Println(p6 == p7)  // true
    
    fmt.Println(p2, p3, p4, s)
}

9.2 结构体标签

package main

import (
    "encoding/json"
    "fmt"
    "reflect"
)

// 结构体标签
type User struct {
    ID       int    `json:"id" db:"user_id"`
    Username string `json:"username" db:"user_name"`
    Email    string `json:"email,omitempty" db:"email"`
    Password string `json:"-" db:"password"`  // json:"-" 表示忽略该字段
}

func main() {
    user := User{
        ID:       1,
        Username: "alice",
        Email:    "alice@example.com",
        Password: "secret",
    }
    
    // JSON序列化
    jsonData, _ := json.Marshal(user)
    fmt.Println(string(jsonData))
    // 输出: {"id":1,"username":"alice","email":"alice@example.com"}
    
    // JSON反序列化
    jsonStr := `{"id":2,"username":"bob","email":"bob@example.com"}`
    var user2 User
    json.Unmarshal([]byte(jsonStr), &user2)
    fmt.Println(user2)
    
    // 使用反射读取标签
    t := reflect.TypeOf(user)
    field, _ := t.FieldByName("Username")
    fmt.Println(field.Tag.Get("json"))  // username
    fmt.Println(field.Tag.Get("db"))    // user_name
}

10. 方法和接口

10.1 方法

package main

import (
    "fmt"
    "math"
)

// 定义结构体
type Circle struct {
    Radius float64
}

type Rectangle struct {
    Width  float64
    Height float64
}

// 值接收者方法
func (c Circle) Area() float64 {
    return math.Pi * c.Radius * c.Radius
}

// 指针接收者方法
func (c *Circle) Scale(factor float64) {
    c.Radius *= factor
}

// Rectangle的方法
func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

func (r *Rectangle) Scale(factor float64) {
    r.Width *= factor
    r.Height *= factor
}

func main() {
    c := Circle{Radius: 5}
    fmt.Println("面积:", c.Area())
    
    c.Scale(2)
    fmt.Println("缩放后半径:", c.Radius)
    
    r := Rectangle{Width: 10, Height: 5}
    fmt.Println("面积:", r.Area())
    
    r.Scale(2)
    fmt.Println("缩放后:", r.Width, r.Height)
}

10.2 接口

package main

import (
    "fmt"
    "math"
)

// 定义接口
type Shape interface {
    Area() float64
    Perimeter() float64
}

// 实现接口
type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return math.Pi * c.Radius * c.Radius
}

func (c Circle) Perimeter() float64 {
    return 2 * math.Pi * c.Radius
}

type Rectangle struct {
    Width  float64
    Height float64
}

func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

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

// 使用接口作为参数
func PrintShapeInfo(s Shape) {
    fmt.Printf("面积: %.2f, 周长: %.2f\n", s.Area(), s.Perimeter())
}

func main() {
    c := Circle{Radius: 5}
    r := Rectangle{Width: 10, Height: 5}
    
    PrintShapeInfo(c)
    PrintShapeInfo(r)
    
    // 接口切片
    shapes := []Shape{c, r}
    for _, shape := range shapes {
        PrintShapeInfo(shape)
    }
}

10.3 空接口和类型断言

package main

import "fmt"

func main() {
    // 空接口可以存储任何类型
    var i interface{}
    
    i = 42
    fmt.Println(i)
    
    i = "hello"
    fmt.Println(i)
    
    i = []int{1, 2, 3}
    fmt.Println(i)
    
    // 类型断言
    var x interface{} = "hello"
    
    // 方式1:直接断言
    s := x.(string)
    fmt.Println(s)
    
    // 方式2:安全断言
    s2, ok := x.(string)
    if ok {
        fmt.Println("是字符串:", s2)
    }
    
    // 类型switch
    describe(42)
    describe("hello")
    describe(true)
    describe([]int{1, 2, 3})
}

func describe(i interface{}) {
    switch v := i.(type) {
    case int:
        fmt.Printf("整数: %d\n", v)
    case string:
        fmt.Printf("字符串: %s\n", v)
    case bool:
        fmt.Printf("布尔: %t\n", v)
    default:
        fmt.Printf("未知类型: %T\n", v)
    }
}

10.4 接口组合

package main

import "fmt"

// 基础接口
type Reader interface {
    Read() string
}

type Writer interface {
    Write(string)
}

// 组合接口
type ReadWriter interface {
    Reader
    Writer
}

// 实现组合接口
type File struct {
    content string
}

func (f *File) Read() string {
    return f.content
}

func (f *File) Write(content string) {
    f.content = content
}

func main() {
    file := &File{}
    
    // File实现了ReadWriter接口
    var rw ReadWriter = file
    
    rw.Write("Hello, World!")
    fmt.Println(rw.Read())
}

11. 并发编程

11.1 Goroutine

package main

import (
    "fmt"
    "time"
)

func sayHello() {
    for i := 0; i < 5; i++ {
        fmt.Println("Hello", i)
        time.Sleep(100 * time.Millisecond)
    }
}

func sayWorld() {
    for i := 0; i < 5; i++ {
        fmt.Println("World", i)
        time.Sleep(100 * time.Millisecond)
    }
}

func main() {
    // 启动goroutine
    go sayHello()
    go sayWorld()
    
    // 匿名goroutine
    go func() {
        fmt.Println("匿名goroutine")
    }()
    
    // 等待goroutine完成
    time.Sleep(1 * time.Second)
    
    fmt.Println("主程序结束")
}

11.2 Channel

package main

import "fmt"

func main() {
    // 创建channel
    ch := make(chan int)
    
    // 发送数据到channel(在goroutine中)
    go func() {
        ch <- 42  // 发送
    }()
    
    // 从channel接收数据
    value := <-ch  // 接收
    fmt.Println(value)
    
    // 带缓冲的channel
    bufferedCh := make(chan int, 3)
    bufferedCh <- 1
    bufferedCh <- 2
    bufferedCh <- 3
    
    fmt.Println(<-bufferedCh)
    fmt.Println(<-bufferedCh)
    fmt.Println(<-bufferedCh)
    
    // 关闭channel
    ch2 := make(chan int, 2)
    ch2 <- 1
    ch2 <- 2
    close(ch2)
    
    // 遍历channel
    for v := range ch2 {
        fmt.Println(v)
    }
    
    // 检查channel是否关闭
    ch3 := make(chan int, 1)
    ch3 <- 100
    close(ch3)
    
    v, ok := <-ch3
    if ok {
        fmt.Println("接收到:", v)
    } else {
        fmt.Println("channel已关闭")
    }
}

11.3 Select语句

package main

import (
    "fmt"
    "time"
)

func main() {
    ch1 := make(chan string)
    ch2 := make(chan string)
    
    go func() {
        time.Sleep(1 * time.Second)
        ch1 <- "来自ch1"
    }()
    
    go func() {
        time.Sleep(2 * time.Second)
        ch2 <- "来自ch2"
    }()
    
    // select等待多个channel操作
    for i := 0; i < 2; i++ {
        select {
        case msg1 := <-ch1:
            fmt.Println(msg1)
        case msg2 := <-ch2:
            fmt.Println(msg2)
        case <-time.After(3 * time.Second):
            fmt.Println("超时")
        }
    }
    
    // 非阻塞select
    ch3 := make(chan int, 1)
    select {
    case ch3 <- 1:
        fmt.Println("发送成功")
    default:
        fmt.Println("无法发送")
    }
}

11.4 WaitGroup

package main

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

func worker(id int, wg *sync.WaitGroup) {
    defer wg.Done()  // 完成时调用Done
    
    fmt.Printf("Worker %d 开始\n", id)
    time.Sleep(time.Second)
    fmt.Printf("Worker %d 完成\n", id)
}

func main() {
    var wg sync.WaitGroup
    
    // 启动5个worker
    for i := 1; i <= 5; i++ {
        wg.Add(1)  // 增加计数
        go worker(i, &wg)
    }
    
    // 等待所有worker完成
    wg.Wait()
    fmt.Println("所有worker完成")
}

11.5 Mutex互斥锁

package main

import (
    "fmt"
    "sync"
)

type Counter struct {
    mu    sync.Mutex
    value int
}

func (c *Counter) Increment() {
    c.mu.Lock()
    defer c.mu.Unlock()
    c.value++
}

func (c *Counter) Value() int {
    c.mu.Lock()
    defer c.mu.Unlock()
    return c.value
}

func main() {
    counter := &Counter{}
    var wg sync.WaitGroup
    
    // 启动1000个goroutine,每个增加计数器
    for i := 0; i < 1000; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            counter.Increment()
        }()
    }
    
    wg.Wait()
    fmt.Println("最终值:", counter.Value())  // 1000
}

11.6 并发模式

package main

import (
    "fmt"
    "time"
)

// 生产者-消费者模式
func producer(ch chan<- int) {
    for i := 0; i < 5; i++ {
        ch <- i
        fmt.Println("生产:", i)
        time.Sleep(time.Millisecond * 500)
    }
    close(ch)
}

func consumer(ch <-chan int) {
    for v := range ch {
        fmt.Println("消费:", v)
        time.Sleep(time.Millisecond * 1000)
    }
}

// Worker Pool模式
func worker(id int, jobs <-chan int, results chan<- int) {
    for j := range jobs {
        fmt.Printf("Worker %d 处理任务 %d\n", id, j)
        time.Sleep(time.Second)
        results <- j * 2
    }
}

func workerPool() {
    jobs := make(chan int, 100)
    results := make(chan int, 100)
    
    // 启动3个worker
    for w := 1; w <= 3; w++ {
        go worker(w, jobs, results)
    }
    
    // 发送9个任务
    for j := 1; j <= 9; j++ {
        jobs <- j
    }
    close(jobs)
    
    // 收集结果
    for a := 1; a <= 9; a++ {
        <-results
    }
}

func main() {
    // 生产者-消费者
    ch := make(chan int, 2)
    go producer(ch)
    consumer(ch)
    
    // Worker Pool
    workerPool()
}

12. 错误处理

12.1 错误基础

package main

import (
    "errors"
    "fmt"
)

// 返回错误
func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("除数不能为0")
    }
    return a / b, nil
}

// 使用fmt.Errorf
func validateAge(age int) error {
    if age < 0 {
        return fmt.Errorf("年龄不能为负数: %d", age)
    }
    if age > 150 {
        return fmt.Errorf("年龄过大: %d", age)
    }
    return nil
}

func main() {
    // 处理错误
    result, err := divide(10, 0)
    if err != nil {
        fmt.Println("错误:", err)
    } else {
        fmt.Println("结果:", result)
    }
    
    // 验证年龄
    if err := validateAge(-5); err != nil {
        fmt.Println(err)
    }
}

12.2 自定义错误类型

package main

import "fmt"

// 自定义错误类型
type ValidationError struct {
    Field string
    Value interface{}
    Msg   string
}

func (e *ValidationError) Error() string {
    return fmt.Sprintf("验证错误 [%s]: %v - %s", e.Field, e.Value, e.Msg)
}

func validateUser(name string, age int) error {
    if name == "" {
        return &ValidationError{
            Field: "name",
            Value: name,
            Msg:   "名字不能为空",
        }
    }
    if age < 18 {
        return &ValidationError{
            Field: "age",
            Value: age,
            Msg:   "年龄必须大于18",
        }
    }
    return nil
}

func main() {
    err := validateUser("", 15)
    if err != nil {
        // 类型断言
        if ve, ok := err.(*ValidationError); ok {
            fmt.Printf("字段: %s, 值: %v, 消息: %s\n", 
                ve.Field, ve.Value, ve.Msg)
        }
    }
}

12.3 错误包装(Go 1.13+)

package main

import (
    "errors"
    "fmt"
)

var ErrNotFound = errors.New("未找到")

func findUser(id int) error {
    // 模拟查找失败
    return fmt.Errorf("查找用户 %d: %w", id, ErrNotFound)
}

func main() {
    err := findUser(123)
    
    // 检查错误
    if errors.Is(err, ErrNotFound) {
        fmt.Println("用户不存在")
    }
    
    // 解包错误
    fmt.Println(errors.Unwrap(err))
}

12.4 Panic和Recover

package main

import "fmt"

func riskyOperation() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("恢复自panic:", r)
        }
    }()
    
    fmt.Println("开始危险操作")
    panic("出错了!")
    fmt.Println("这行不会执行")
}

func main() {
    riskyOperation()
    fmt.Println("程序继续运行")
}

13. 包管理

13.1 创建包

// mypackage/math.go
package mypackage

// 导出的函数(首字母大写)
func Add(a, b int) int {
    return a + b
}

// 未导出的函数(首字母小写)
func subtract(a, b int) int {
    return a - b
}

// 导出的常量
const PI = 3.14159

// 未导出的变量
var internalVar = "internal"

13.2 使用包

// main.go
package main

import (
    "fmt"
    "myproject/mypackage"
)

func main() {
    result := mypackage.Add(3, 5)
    fmt.Println(result)
    
    fmt.Println(mypackage.PI)
}

13.3 Go Modules

# 初始化模块
go mod init github.com/username/project

# 添加依赖
go get github.com/gin-gonic/gin

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

# 下载依赖
go mod download

# 整理依赖
go mod tidy

# 查看依赖
go list -m all

# 验证依赖
go mod verify

13.4 go.mod文件

module github.com/username/project

go 1.21

require (
    github.com/gin-gonic/gin v1.9.1
    github.com/go-sql-driver/mysql v1.7.1
)

require (
    github.com/bytedance/sonic v1.9.1 // indirect
    github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
)

replace github.com/old/package => github.com/new/package v1.0.0

14. 文件操作

14.1 读取文件

package main

import (
    "bufio"
    "fmt"
    "io"
    "io/ioutil"
    "os"
)

func main() {
    // 方式1:一次性读取整个文件
    content, err := ioutil.ReadFile("test.txt")
    if err != nil {
        fmt.Println("错误:", err)
        return
    }
    fmt.Println(string(content))
    
    // 方式2:使用os.Open
    file, err := os.Open("test.txt")
    if err != nil {
        fmt.Println("错误:", err)
        return
    }
    defer file.Close()
    
    // 读取文件内容
    data := make([]byte, 100)
    count, err := file.Read(data)
    if err != nil && err != io.EOF {
        fmt.Println("错误:", err)
        return
    }
    fmt.Printf("读取了 %d 字节: %s\n", count, data[:count])
    
    // 方式3:使用bufio逐行读取
    file2, _ := os.Open("test.txt")
    defer file2.Close()
    
    scanner := bufio.NewScanner(file2)
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }
}

14.2 写入文件

package main

import (
    "bufio"
    "fmt"
    "io/ioutil"
    "os"
)

func main() {
    // 方式1:一次性写入
    content := []byte("Hello, World!\n")
    err := ioutil.WriteFile("output.txt", content, 0644)
    if err != nil {
        fmt.Println("错误:", err)
        return
    }
    
    // 方式2:使用os.Create
    file, err := os.Create("output2.txt")
    if err != nil {
        fmt.Println("错误:", err)
        return
    }
    defer file.Close()
    
    file.WriteString("第一行\n")
    file.Write([]byte("第二行\n"))
    
    // 方式3:使用bufio
    writer := bufio.NewWriter(file)
    writer.WriteString("第三行\n")
    writer.Flush()  // 刷新缓冲区
    
    // 追加模式
    file2, err := os.OpenFile("output.txt", 
        os.O_APPEND|os.O_WRONLY, 0644)
    if err != nil {
        fmt.Println("错误:", err)
        return
    }
    defer file2.Close()
    
    file2.WriteString("追加的内容\n")
}

14.3 文件操作

package main

import (
    "fmt"
    "os"
    "path/filepath"
)

func main() {
    // 检查文件是否存在
    if _, err := os.Stat("test.txt"); os.IsNotExist(err) {
        fmt.Println("文件不存在")
    }
    
    // 创建目录
    os.Mkdir("testdir", 0755)
    os.MkdirAll("path/to/dir", 0755)  // 创建多级目录
    
    // 删除文件
    os.Remove("test.txt")
    
    // 删除目录
    os.RemoveAll("testdir")
    
    // 重命名/移动文件
    os.Rename("old.txt", "new.txt")
    
    // 获取文件信息
    fileInfo, err := os.Stat("test.txt")
    if err == nil {
        fmt.Println("文件名:", fileInfo.Name())
        fmt.Println("大小:", fileInfo.Size())
        fmt.Println("权限:", fileInfo.Mode())
        fmt.Println("修改时间:", fileInfo.ModTime())
        fmt.Println("是否目录:", fileInfo.IsDir())
    }
    
    // 遍历目录
    filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }
        fmt.Println(path)
        return nil
    })
    
    // 读取目录
    files, err := ioutil.ReadDir(".")
    if err == nil {
        for _, file := range files {
            fmt.Println(file.Name())
        }
    }
}

15. 网络编程

15.1 HTTP客户端

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
)

func main() {
    // GET请求
    resp, err := http.Get("https://api.github.com")
    if err != nil {
        fmt.Println("错误:", err)
        return
    }
    defer resp.Body.Close()
    
    body, _ := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body))
    
    // POST请求
    data := map[string]string{
        "name":  "Alice",
        "email": "alice@example.com",
    }
    jsonData, _ := json.Marshal(data)
    
    resp2, err := http.Post(
        "https://httpbin.org/post",
        "application/json",
        bytes.NewBuffer(jsonData),
    )
    if err != nil {
        fmt.Println("错误:", err)
        return
    }
    defer resp2.Body.Close()
    
    // 自定义请求
    client := &http.Client{}
    req, _ := http.NewRequest("GET", "https://api.github.com", nil)
    req.Header.Add("Authorization", "Bearer token")
    
    resp3, err := client.Do(req)
    if err != nil {
        fmt.Println("错误:", err)
        return
    }
    defer resp3.Body.Close()
}

15.2 HTTP服务器

package main

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

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

// 处理函数
func homeHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "欢迎访问首页!")
}

func userHandler(w http.ResponseWriter, r *http.Request) {
    if r.Method == "GET" {
        user := User{Name: "Alice", Email: "alice@example.com"}
        json.NewEncoder(w).Encode(user)
    } else if r.Method == "POST" {
        var user User
        json.NewDecoder(r.Body).Decode(&user)
        fmt.Fprintf(w, "创建用户: %s", user.Name)
    }
}

func main() {
    // 注册路由
    http.HandleFunc("/", homeHandler)
    http.HandleFunc("/user", userHandler)
    
    // 静态文件服务
    fs := http.FileServer(http.Dir("./static"))
    http.Handle("/static/", http.StripPrefix("/static/", fs))
    
    // 启动服务器
    fmt.Println("服务器启动在 :8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

15.3 TCP编程

package main

import (
    "bufio"
    "fmt"
    "net"
)

// TCP服务器
func startTCPServer() {
    listener, err := net.Listen("tcp", ":8888")
    if err != nil {
        fmt.Println("错误:", err)
        return
    }
    defer listener.Close()
    
    fmt.Println("TCP服务器启动在 :8888")
    
    for {
        conn, err := listener.Accept()
        if err != nil {
            fmt.Println("错误:", err)
            continue
        }
        
        go handleConnection(conn)
    }
}

func handleConnection(conn net.Conn) {
    defer conn.Close()
    
    reader := bufio.NewReader(conn)
    for {
        message, err := reader.ReadString('\n')
        if err != nil {
            return
        }
        
        fmt.Print("收到消息: ", message)
        conn.Write([]byte("收到: " + message))
    }
}

// TCP客户端
func startTCPClient() {
    conn, err := net.Dial("tcp", "localhost:8888")
    if err != nil {
        fmt.Println("错误:", err)
        return
    }
    defer conn.Close()
    
    // 发送消息
    conn.Write([]byte("Hello, Server!\n"))
    
    // 接收响应
    buffer := make([]byte, 1024)
    n, _ := conn.Read(buffer)
    fmt.Println("收到响应:", string(buffer[:n]))
}

15.4 WebSocket

package main

import (
    "fmt"
    "log"
    "net/http"
    
    "github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
    CheckOrigin: func(r *http.Request) bool {
        return true
    },
}

func wsHandler(w http.ResponseWriter, r *http.Request) {
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println(err)
        return
    }
    defer conn.Close()
    
    for {
        messageType, message, err := conn.ReadMessage()
        if err != nil {
            log.Println(err)
            break
        }
        
        fmt.Printf("收到: %s\n", message)
        
        err = conn.WriteMessage(messageType, message)
        if err != nil {
            log.Println(err)
            break
        }
    }
}

func main() {
    http.HandleFunc("/ws", wsHandler)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

16. 数据库操作

16.1 MySQL操作

package main

import (
    "database/sql"
    "fmt"
    "log"
    
    _ "github.com/go-sql-driver/mysql"
)

type User struct {
    ID    int
    Name  string
    Email string
}

func main() {
    // 连接数据库
    db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/dbname")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()
    
    // 测试连接
    err = db.Ping()
    if err != nil {
        log.Fatal(err)
    }
    
    // 插入数据
    result, err := db.Exec("INSERT INTO users (name, email) VALUES (?, ?)", 
        "Alice", "alice@example.com")
    if err != nil {
        log.Fatal(err)
    }
    
    lastID, _ := result.LastInsertId()
    rowsAffected, _ := result.RowsAffected()
    fmt.Printf("插入ID: %d, 影响行数: %d\n", lastID, rowsAffected)
    
    // 查询单行
    var user User
    err = db.QueryRow("SELECT id, name, email FROM users WHERE id = ?", 1).
        Scan(&user.ID, &user.Name, &user.Email)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("用户: %+v\n", user)
    
    // 查询多行
    rows, err := db.Query("SELECT id, name, email FROM users")
    if err != nil {
        log.Fatal(err)
    }
    defer rows.Close()
    
    for rows.Next() {
        var u User
        err := rows.Scan(&u.ID, &u.Name, &u.Email)
        if err != nil {
            log.Fatal(err)
        }
        fmt.Printf("用户: %+v\n", u)
    }
    
    // 更新数据
    _, err = db.Exec("UPDATE users SET email = ? WHERE id = ?", 
        "newemail@example.com", 1)
    
    // 删除数据
    _, err = db.Exec("DELETE FROM users WHERE id = ?", 1)
    
    // 事务
    tx, err := db.Begin()
    if err != nil {
        log.Fatal(err)
    }
    
    _, err = tx.Exec("INSERT INTO users (name, email) VALUES (?, ?)", 
        "Bob", "bob@example.com")
    if err != nil {
        tx.Rollback()
        log.Fatal(err)
    }
    
    err = tx.Commit()
    if err != nil {
        log.Fatal(err)
    }
}

16.2 Redis操作

package main

import (
    "context"
    "fmt"
    "time"
    
    "github.com/go-redis/redis/v8"
)

var ctx = context.Background()

func main() {
    // 创建客户端
    rdb := redis.NewClient(&redis.Options{
        Addr:     "localhost:6379",
        Password: "",
        DB:       0,
    })
    
    // 测试连接
    pong, err := rdb.Ping(ctx).Result()
    fmt.Println(pong, err)
    
    // 字符串操作
    err = rdb.Set(ctx, "key", "value", 0).Err()
    if err != nil {
        panic(err)
    }
    
    val, err := rdb.Get(ctx, "key").Result()
    if err != nil {
        panic(err)
    }
    fmt.Println("key:", val)
    
    // 设置过期时间
    err = rdb.Set(ctx, "key2", "value2", 10*time.Second).Err()
    
    // 列表操作
    rdb.RPush(ctx, "list", "item1", "item2", "item3")
    items, _ := rdb.LRange(ctx, "list", 0, -1).Result()
    fmt.Println("列表:", items)
    
    // 哈希操作
    rdb.HSet(ctx, "user:1", "name", "Alice")
    rdb.HSet(ctx, "user:1", "email", "alice@example.com")
    name, _ := rdb.HGet(ctx, "user:1", "name").Result()
    fmt.Println("用户名:", name)
    
    // 集合操作
    rdb.SAdd(ctx, "set", "member1", "member2", "member3")
    members, _ := rdb.SMembers(ctx, "set").Result()
    fmt.Println("集合:", members)
    
    // 有序集合
    rdb.ZAdd(ctx, "scores", &redis.Z{Score: 90, Member: "Alice"})
    rdb.ZAdd(ctx, "scores", &redis.Z{Score: 85, Member: "Bob"})
    scores, _ := rdb.ZRangeWithScores(ctx, "scores", 0, -1).Result()
    fmt.Println("排行榜:", scores)
}

16.3 MongoDB操作

package main

import (
    "context"
    "fmt"
    "log"
    "time"
    
    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

type User struct {
    Name  string `bson:"name"`
    Email string `bson:"email"`
    Age   int    `bson:"age"`
}

func main() {
    // 连接MongoDB
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    
    client, err := mongo.Connect(ctx, options.Client().
        ApplyURI("mongodb://localhost:27017"))
    if err != nil {
        log.Fatal(err)
    }
    defer client.Disconnect(ctx)
    
    // 选择数据库和集合
    collection := client.Database("testdb").Collection("users")
    
    // 插入单个文档
    user := User{Name: "Alice", Email: "alice@example.com", Age: 25}
    result, err := collection.InsertOne(ctx, user)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("插入ID:", result.InsertedID)
    
    // 插入多个文档
    users := []interface{}{
        User{Name: "Bob", Email: "bob@example.com", Age: 30},
        User{Name: "Charlie", Email: "charlie@example.com", Age: 35},
    }
    results, _ := collection.InsertMany(ctx, users)
    fmt.Println("插入IDs:", results.InsertedIDs)
    
    // 查询单个文档
    var foundUser User
    err = collection.FindOne(ctx, bson.M{"name": "Alice"}).Decode(&foundUser)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("找到用户: %+v\n", foundUser)
    
    // 查询多个文档
    cursor, err := collection.Find(ctx, bson.M{"age": bson.M{"$gte": 25}})
    if err != nil {
        log.Fatal(err)
    }
    defer cursor.Close(ctx)
    
    for cursor.Next(ctx) {
        var u User
        cursor.Decode(&u)
        fmt.Printf("用户: %+v\n", u)
    }
    
    // 更新文档
    update := bson.M{"$set": bson.M{"age": 26}}
    _, err = collection.UpdateOne(ctx, bson.M{"name": "Alice"}, update)
    
    // 删除文档
    _, err = collection.DeleteOne(ctx, bson.M{"name": "Bob"})
}

17. 测试

17.1 单元测试

// math.go
package math

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

func Subtract(a, b int) int {
    return a - b
}

func Multiply(a, b int) int {
    return a * b
}

func Divide(a, b int) (int, error) {
    if b == 0 {
        return 0, errors.New("除数不能为0")
    }
    return a / b, nil
}
// math_test.go
package math

import "testing"

func TestAdd(t *testing.T) {
    result := Add(2, 3)
    expected := 5
    
    if result != expected {
        t.Errorf("Add(2, 3) = %d; 期望 %d", result, expected)
    }
}

func TestSubtract(t *testing.T) {
    tests := []struct {
        name     string
        a, b     int
        expected int
    }{
        {"正数", 5, 3, 2},
        {"负数", 3, 5, -2},
        {"零", 5, 5, 0},
    }
    
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            result := Subtract(tt.a, tt.b)
            if result != tt.expected {
                t.Errorf("Subtract(%d, %d) = %d; 期望 %d", 
                    tt.a, tt.b, result, tt.expected)
            }
        })
    }
}

func TestDivide(t *testing.T) {
    // 正常情况
    result, err := Divide(10, 2)
    if err != nil {
        t.Errorf("意外错误: %v", err)
    }
    if result != 5 {
        t.Errorf("Divide(10, 2) = %d; 期望 5", result)
    }
    
    // 除以零
    _, err = Divide(10, 0)
    if err == nil {
        t.Error("期望错误,但没有返回错误")
    }
}

17.2 基准测试

// math_test.go
package math

import "testing"

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

func BenchmarkMultiply(b *testing.B) {
    for i := 0; i < b.N; i++ {
        Multiply(2, 3)
    }
}

运行测试:

# 运行所有测试
go test

# 运行详细测试
go test -v

# 运行特定测试
go test -run TestAdd

# 运行基准测试
go test -bench=.

# 生成覆盖率报告
go test -cover
go test -coverprofile=coverage.out
go tool cover -html=coverage.out

17.3 示例测试

// math_test.go
package math

import "fmt"

func ExampleAdd() {
    result := Add(2, 3)
    fmt.Println(result)
    // Output: 5
}

func ExampleSubtract() {
    result := Subtract(5, 3)
    fmt.Println(result)
    // Output: 2
}

17.4 Mock测试

package main

import (
    "testing"
)

// 接口
type Database interface {
    GetUser(id int) (string, error)
}

// Mock实现
type MockDatabase struct {
    GetUserFunc func(id int) (string, error)
}

func (m *MockDatabase) GetUser(id int) (string, error) {
    return m.GetUserFunc(id)
}

// 被测试的函数
func GetUserName(db Database, id int) string {
    name, err := db.GetUser(id)
    if err != nil {
        return "Unknown"
    }
    return name
}

// 测试
func TestGetUserName(t *testing.T) {
    mockDB := &MockDatabase{
        GetUserFunc: func(id int) (string, error) {
            if id == 1 {
                return "Alice", nil
            }
            return "", errors.New("用户不存在")
        },
    }
    
    name := GetUserName(mockDB, 1)
    if name != "Alice" {
        t.Errorf("期望 Alice, 得到 %s", name)
    }
    
    name = GetUserName(mockDB, 999)
    if name != "Unknown" {
        t.Errorf("期望 Unknown, 得到 %s", name)
    }
}

18. 性能优化

18.1 性能分析

package main

import (
    "fmt"
    "os"
    "runtime/pprof"
    "time"
)

func fibonacci(n int) int {
    if n <= 1 {
        return n
    }
    return fibonacci(n-1) + fibonacci(n-2)
}

func main() {
    // CPU性能分析
    cpuFile, _ := os.Create("cpu.prof")
    pprof.StartCPUProfile(cpuFile)
    defer pprof.StopCPUProfile()
    
    // 执行需要分析的代码
    for i := 0; i < 30; i++ {
        fibonacci(i)
    }
    
    // 内存性能分析
    memFile, _ := os.Create("mem.prof")
    defer memFile.Close()
    pprof.WriteHeapProfile(memFile)
}

分析性能数据:

# 分析CPU性能
go tool pprof cpu.prof

# 分析内存性能
go tool pprof mem.prof

# Web界面查看
go tool pprof -http=:8080 cpu.prof

18.2 优化技巧

package main

import (
    "fmt"
    "strings"
    "sync"
)

// 1. 使用strings.Builder代替字符串拼接
func stringConcat() {
    var builder strings.Builder
    for i := 0; i < 1000; i++ {
        builder.WriteString("hello")
    }
    result := builder.String()
    fmt.Println(len(result))
}

// 2. 预分配切片容量
func slicePrealloc() {
    // 好的做法
    slice := make([]int, 0, 1000)
    for i := 0; i < 1000; i++ {
        slice = append(slice, i)
    }
}

// 3. 使用sync.Pool复用对象
var bufferPool = sync.Pool{
    New: func() interface{} {
        return new(strings.Builder)
    },
}

func usePool() {
    builder := bufferPool.Get().(*strings.Builder)
    defer func() {
        builder.Reset()
        bufferPool.Put(builder)
    }()
    
    builder.WriteString("使用对象池")
}

// 4. 避免不必要的内存分配
func avoidAlloc() {
    // 使用值类型而不是指针
    type Point struct {
        X, Y int
    }
    
    points := make([]Point, 1000)
    for i := range points {
        points[i] = Point{X: i, Y: i * 2}
    }
}

// 5. 并发优化
func concurrentProcess() {
    var wg sync.WaitGroup
    jobs := make(chan int, 100)
    results := make(chan int, 100)
    
    // 启动worker池
    for w := 0; w < 10; w++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            for job := range jobs {
                results <- job * 2
            }
        }()
    }
    
    // 发送任务
    go func() {
        for i := 0; i < 100; i++ {
            jobs <- i
        }
        close(jobs)
    }()
    
    // 等待完成
    go func() {
        wg.Wait()
        close(results)
    }()
    
    // 收集结果
    for result := range results {
        _ = result
    }
}

18.3 内存优化

package main

import "runtime"

func main() {
    // 手动触发GC
    runtime.GC()
    
    // 设置GC百分比
    runtime.SetGCPercent(100)
    
    // 获取内存统计
    var m runtime.MemStats
    runtime.ReadMemStats(&m)
    
    fmt.Printf("分配的内存: %v MB\n", m.Alloc/1024/1024)
    fmt.Printf("总分配的内存: %v MB\n", m.TotalAlloc/1024/1024)
    fmt.Printf("系统内存: %v MB\n", m.Sys/1024/1024)
    fmt.Printf("GC次数: %v\n", m.NumGC)
}

19. 实战项目

19.1 RESTful API服务

package main

import (
    "encoding/json"
    "log"
    "net/http"
    "strconv"
    
    "github.com/gorilla/mux"
)

type Book struct {
    ID     int    `json:"id"`
    Title  string `json:"title"`
    Author string `json:"author"`
}

var books []Book
var nextID = 1

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

func getBook(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    params := mux.Vars(r)
    id, _ := strconv.Atoi(params["id"])
    
    for _, book := range books {
        if book.ID == id {
            json.NewEncoder(w).Encode(book)
            return
        }
    }
    
    http.Error(w, "Book not found", http.StatusNotFound)
}

func createBook(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    var book Book
    json.NewDecoder(r.Body).Decode(&book)
    book.ID = nextID
    nextID++
    books = append(books, book)
    json.NewEncoder(w).Encode(book)
}

func updateBook(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    params := mux.Vars(r)
    id, _ := strconv.Atoi(params["id"])
    
    for i, book := range books {
        if book.ID == id {
            books = append(books[:i], books[i+1:]...)
            var updatedBook Book
            json.NewDecoder(r.Body).Decode(&updatedBook)
            updatedBook.ID = id
            books = append(books, updatedBook)
            json.NewEncoder(w).Encode(updatedBook)
            return
        }
    }
    
    http.Error(w, "Book not found", http.StatusNotFound)
}

func deleteBook(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    params := mux.Vars(r)
    id, _ := strconv.Atoi(params["id"])
    
    for i, book := range books {
        if book.ID == id {
            books = append(books[:i], books[i+1:]...)
            json.NewEncoder(w).Encode(map[string]string{"message": "Book deleted"})
            return
        }
    }
    
    http.Error(w, "Book not found", http.StatusNotFound)
}

func main() {
    router := mux.NewRouter()
    
    router.HandleFunc("/api/books", getBooks).Methods("GET")
    router.HandleFunc("/api/books/{id}", getBook).Methods("GET")
    router.HandleFunc("/api/books", createBook).Methods("POST")
    router.HandleFunc("/api/books/{id}", updateBook).Methods("PUT")
    router.HandleFunc("/api/books/{id}", deleteBook).Methods("DELETE")
    
    log.Println("服务器启动在 :8000")
    log.Fatal(http.ListenAndServe(":8000", router))
}

19.2 命令行工具

package main

import (
    "flag"
    "fmt"
    "os"
)

func main() {
    // 定义命令行参数
    var (
        name    = flag.String("name", "World", "要问候的名字")
        age     = flag.Int("age", 0, "年龄")
        verbose = flag.Bool("verbose", false, "详细输出")
    )
    
    flag.Parse()
    
    if *verbose {
        fmt.Printf("名字: %s\n", *name)
        fmt.Printf("年龄: %d\n", *age)
    }
    
    fmt.Printf("Hello, %s!\n", *name)
    
    // 处理非标志参数
    args := flag.Args()
    if len(args) > 0 {
        fmt.Println("其他参数:", args)
    }
}

19.3 Web爬虫

package main

import (
    "fmt"
    "log"
    "net/http"
    "strings"
    
    "github.com/PuerkitoBio/goquery"
)

func scrape(url string) {
    // 发送HTTP请求
    res, err := http.Get(url)
    if err != nil {
        log.Fatal(err)
    }
    defer res.Body.Close()
    
    if res.StatusCode != 200 {
        log.Fatalf("状态码错误: %d %s", res.StatusCode, res.Status)
    }
    
    // 解析HTML
    doc, err := goquery.NewDocumentFromReader(res.Body)
    if err != nil {
        log.Fatal(err)
    }
    
    // 提取数据
    doc.Find("a").Each(func(i int, s *goquery.Selection) {
        href, exists := s.Attr("href")
        if exists {
            text := strings.TrimSpace(s.Text())
            fmt.Printf("链接: %s, 文本: %s\n", href, text)
        }
    })
}

func main() {
    scrape("https://example.com")
}

20. 进阶主题

20.1 反射

package main

import (
    "fmt"
    "reflect"
)

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

func main() {
    p := Person{Name: "Alice", Age: 25}
    
    // 获取类型
    t := reflect.TypeOf(p)
    fmt.Println("类型:", t)
    fmt.Println("类型名:", t.Name())
    fmt.Println("类型种类:", t.Kind())
    
    // 获取值
    v := reflect.ValueOf(p)
    fmt.Println("值:", v)
    
    // 遍历字段
    for i := 0; i < t.NumField(); i++ {
        field := t.Field(i)
        value := v.Field(i)
        fmt.Printf("字段: %s, 类型: %s, 值: %v, 标签: %s\n",
            field.Name, field.Type, value, field.Tag.Get("json"))
    }
    
    // 修改值(需要指针)
    pv := reflect.ValueOf(&p)
    pv.Elem().FieldByName("Age").SetInt(26)
    fmt.Println("修改后:", p)
    
    // 调用方法
    method := v.MethodByName("String")
    if method.IsValid() {
        result := method.Call(nil)
        fmt.Println(result)
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小徐Chao努力

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值