跳转到内容

Go语言标准库应用

课程目标

通过本课程的学习,你将掌握Go语言标准库的核心功能和应用场景,包括文件操作、网络编程、并发控制、JSON处理等常用功能,为实际项目开发打下坚实的基础。

1. 标准库概述

1.1 什么是标准库

Go语言标准库是Go语言内置的一系列包,提供了丰富的功能,包括:

  • 基础功能:字符串处理、数学运算、时间操作等
  • 文件操作:文件读写、目录操作等
  • 网络编程:HTTP服务器、TCP/IP通信等
  • 并发控制:goroutine、channel、同步原语等
  • 数据序列化:JSON、XML、CSV等
  • 加密解密:哈希、加密算法等
  • 反射:运行时类型信息等
  • 测试:单元测试、基准测试等

1.2 标准库的优势

  • 稳定性:经过严格测试,稳定可靠
  • 性能:经过优化,性能优异
  • 一致性:API设计一致,易于学习
  • 无需安装:内置在Go语言中,无需额外安装
  • 文档完善:有详细的官方文档

1.3 常用标准库包

包名功能用途
fmt格式化输入输出打印、格式化字符串
os操作系统功能文件操作、环境变量
io输入输出接口流操作、读写接口
net/httpHTTP服务器和客户端构建Web服务、HTTP请求
encoding/jsonJSON编解码数据序列化/反序列化
sync同步原语并发控制、锁、等待组
time时间操作时间格式化、定时器
strconv字符串转换字符串与其他类型互转
strings字符串操作字符串处理、分割、替换
bytes字节操作字节切片处理
path/filepath路径操作文件路径处理、遍历
regexp正则表达式字符串匹配、替换
context上下文管理取消信号、超时控制
crypto加密功能哈希、加密算法
testing测试功能单元测试、基准测试

2. 文件操作

2.1 基本文件操作

2.1.1 创建和打开文件

go
package main

import (
    "fmt"
    "os"
)

func main() {
    // 创建文件
    file, err := os.Create("example.txt")
    if err != nil {
        fmt.Println("Error creating file:", err)
        return
    }
    defer file.Close()
    fmt.Println("File created successfully")
    
    // 打开文件
    file, err = os.Open("example.txt")
    if err != nil {
        fmt.Println("Error opening file:", err)
        return
    }
    defer file.Close()
    fmt.Println("File opened successfully")
    
    // 以读写模式打开文件
    file, err = os.OpenFile("example.txt", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
    if err != nil {
        fmt.Println("Error opening file:", err)
        return
    }
    defer file.Close()
    fmt.Println("File opened in read-write mode")
}

2.1.2 读写文件

go
package main

import (
    "fmt"
    "os"
)

func main() {
    // 写入文件
    file, err := os.Create("example.txt")
    if err != nil {
        fmt.Println("Error creating file:", err)
        return
    }
    
    // 写入字符串
    n, err := file.WriteString("Hello, Go standard library!\n")
    if err != nil {
        fmt.Println("Error writing to file:", err)
        return
    }
    fmt.Printf("Wrote %d bytes\n", n)
    
    // 写入字节切片
    bytes := []byte("Another line\n")
    n, err = file.Write(bytes)
    if err != nil {
        fmt.Println("Error writing to file:", err)
        return
    }
    fmt.Printf("Wrote %d bytes\n", n)
    
    file.Close()
    
    // 读取文件
    file, err = os.Open("example.txt")
    if err != nil {
        fmt.Println("Error opening file:", err)
        return
    }
    defer file.Close()
    
    // 读取全部内容
    fileInfo, err := file.Stat()
    if err != nil {
        fmt.Println("Error getting file info:", err)
        return
    }
    
    buffer := make([]byte, fileInfo.Size())
    n, err = file.Read(buffer)
    if err != nil {
        fmt.Println("Error reading file:", err)
        return
    }
    fmt.Printf("Read %d bytes:\n%s", n, buffer)
}

2.1.3 逐行读取文件

go
package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    file, err := os.Open("example.txt")
    if err != nil {
        fmt.Println("Error opening file:", err)
        return
    }
    defer file.Close()
    
    scanner := bufio.NewScanner(file)
    lineNum := 1
    
    for scanner.Scan() {
        line := scanner.Text()
        fmt.Printf("Line %d: %s\n", lineNum, line)
        lineNum++
    }
    
    if err := scanner.Err(); err != nil {
        fmt.Println("Error scanning file:", err)
    }
}

2.2 目录操作

2.2.1 创建和删除目录

go
package main

import (
    "fmt"
    "os"
)

func main() {
    // 创建目录
    err := os.Mkdir("testdir", 0755)
    if err != nil {
        fmt.Println("Error creating directory:", err)
        return
    }
    fmt.Println("Directory created successfully")
    
    // 创建多级目录
    err = os.MkdirAll("parent/child/grandchild", 0755)
    if err != nil {
        fmt.Println("Error creating nested directories:", err)
        return
    }
    fmt.Println("Nested directories created successfully")
    
    // 删除目录
    err = os.Remove("testdir")
    if err != nil {
        fmt.Println("Error removing directory:", err)
        return
    }
    fmt.Println("Directory removed successfully")
    
    // 删除多级目录
    err = os.RemoveAll("parent")
    if err != nil {
        fmt.Println("Error removing nested directories:", err)
        return
    }
    fmt.Println("Nested directories removed successfully")
}

2.2.2 遍历目录

go
package main

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

func main() {
    // 遍历目录
    err := filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }
        
        if info.IsDir() {
            fmt.Printf("[DIR]  %s\n", path)
        } else {
            fmt.Printf("[FILE] %s (size: %d bytes)\n", path, info.Size())
        }
        return nil
    })
    
    if err != nil {
        fmt.Println("Error walking directory:", err)
    }
}

2.3 临时文件和目录

go
package main

import (
    "fmt"
    "os"
)

func main() {
    // 创建临时文件
    tempFile, err := os.CreateTemp(".", "temp-*.txt")
    if err != nil {
        fmt.Println("Error creating temp file:", err)
        return
    }
    defer os.Remove(tempFile.Name()) // 清理临时文件
    defer tempFile.Close()
    
    fmt.Printf("Created temp file: %s\n", tempFile.Name())
    
    // 写入数据
    tempFile.WriteString("Temporary data")
    
    // 创建临时目录
    tempDir, err := os.MkdirTemp(".", "temp-*")
    if err != nil {
        fmt.Println("Error creating temp directory:", err)
        return
    }
    defer os.RemoveAll(tempDir) // 清理临时目录
    
    fmt.Printf("Created temp directory: %s\n", tempDir)
    
    // 在临时目录中创建文件
    tempFileInDir, err := os.Create(tempDir + "/test.txt")
    if err != nil {
        fmt.Println("Error creating file in temp directory:", err)
        return
    }
    defer tempFileInDir.Close()
    
    tempFileInDir.WriteString("File in temp directory")
    fmt.Println("Created file in temp directory")
}

3. 网络编程

3.1 HTTP服务器

3.1.1 基本HTTP服务器

go
package main

import (
    "fmt"
    "net/http"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, HTTP Server!\n")
    fmt.Fprintf(w, "Method: %s\n", r.Method)
    fmt.Fprintf(w, "URL: %s\n", r.URL.Path)
    fmt.Fprintf(w, "Host: %s\n", r.Host)
}

func main() {
    http.HandleFunc("/", helloHandler)
    
    fmt.Println("Server starting on port 8080...")
    if err := http.ListenAndServe(":8080", nil); err != nil {
        fmt.Println("Error starting server:", err)
    }
}

3.1.2 自定义HTTP服务器

go
package main

import (
    "fmt"
    "net/http"
    "time"
)

func main() {
    // 创建自定义服务器
    server := &http.Server{
        Addr:         ":8080",
        Handler:      http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            fmt.Fprintf(w, "Hello from custom server!\n")
            fmt.Fprintf(w, "Time: %s\n", time.Now().Format(time.RFC3339))
        }),
        ReadTimeout:  10 * time.Second,
        WriteTimeout: 10 * time.Second,
        IdleTimeout:  120 * time.Second,
    }
    
    fmt.Println("Custom server starting on port 8080...")
    if err := server.ListenAndServe(); err != nil {
        fmt.Println("Error starting server:", err)
    }
}

3.2 HTTP客户端

3.2.1 基本HTTP请求

go
package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
)

func main() {
    // 发送GET请求
    resp, err := http.Get("https://example.com")
    if err != nil {
        fmt.Println("Error sending request:", err)
        return
    }
    defer resp.Body.Close()
    
    fmt.Printf("Status: %s\n", resp.Status)
    fmt.Printf("Content-Type: %s\n", resp.Header.Get("Content-Type"))
    
    // 读取响应体
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("Error reading response:", err)
        return
    }
    
    fmt.Printf("Response body length: %d bytes\n", len(body))
    fmt.Println("First 100 bytes:", string(body[:100]))
}

3.2.2 自定义HTTP客户端

go
package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "time"
)

func main() {
    // 创建自定义客户端
    client := &http.Client{
        Timeout: 10 * time.Second,
    }
    
    // 创建请求
    req, err := http.NewRequest("GET", "https://example.com", nil)
    if err != nil {
        fmt.Println("Error creating request:", err)
        return
    }
    
    // 添加请求头
    req.Header.Add("User-Agent", "Go HTTP Client")
    req.Header.Add("Accept", "text/html")
    
    // 发送请求
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("Error sending request:", err)
        return
    }
    defer resp.Body.Close()
    
    fmt.Printf("Status: %s\n", resp.Status)
    
    // 读取响应体
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("Error reading response:", err)
        return
    }
    
    fmt.Printf("Response body length: %d bytes\n", len(body))
}

3.3 TCP服务器和客户端

3.3.1 TCP服务器

go
package main

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

func handleConnection(conn net.Conn) {
    defer conn.Close()
    
    fmt.Printf("Client connected: %s\n", conn.RemoteAddr().String())
    
    scanner := bufio.NewScanner(conn)
    for scanner.Scan() {
        message := scanner.Text()
        fmt.Printf("Received: %s\n", message)
        
        // 发送响应
        conn.Write([]byte("Echo: " + message + "\n"))
        
        if message == "quit" {
            break
        }
    }
    
    fmt.Printf("Client disconnected: %s\n", conn.RemoteAddr().String())
}

func main() {
    listener, err := net.Listen("tcp", ":8080")
    if err != nil {
        fmt.Println("Error starting server:", err)
        return
    }
    defer listener.Close()
    
    fmt.Println("TCP server started on port 8080...")
    
    for {
        conn, err := listener.Accept()
        if err != nil {
            fmt.Println("Error accepting connection:", err)
            continue
        }
        
        go handleConnection(conn)
    }
}

3.3.2 TCP客户端

go
package main

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

func main() {
    conn, err := net.Dial("tcp", "localhost:8080")
    if err != nil {
        fmt.Println("Error connecting to server:", err)
        return
    }
    defer conn.Close()
    
    fmt.Println("Connected to TCP server")
    
    // 读取服务器响应
    go func() {
        scanner := bufio.NewScanner(conn)
        for scanner.Scan() {
            fmt.Println("Server:", scanner.Text())
        }
    }()
    
    // 发送消息
    reader := bufio.NewReader(os.Stdin)
    for {
        fmt.Print("Enter message: ")
        message, _ := reader.ReadString('\n')
        
        conn.Write([]byte(message))
        
        if message == "quit\n" {
            break
        }
    }
}

4. 数据序列化

4.1 JSON处理

4.1.1 JSON序列化

go
package main

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    Name    string `json:"name"`
    Age     int    `json:"age"`
    Email   string `json:"email,omitempty"`
    Address *Address `json:"address,omitempty"`
}

type Address struct {
    City    string `json:"city"`
    Street  string `json:"street"`
    ZipCode string `json:"zip_code"`
}

func main() {
    // 创建结构体实例
    person := Person{
        Name:  "John Doe",
        Age:   30,
        Email: "john@example.com",
        Address: &Address{
            City:    "New York",
            Street:  "123 Main St",
            ZipCode: "10001",
        },
    }
    
    // 序列化为JSON
    jsonData, err := json.Marshal(person)
    if err != nil {
        fmt.Println("Error marshaling JSON:", err)
        return
    }
    
    fmt.Println("JSON:", string(jsonData))
    
    // 美化JSON
    prettyJSON, err := json.MarshalIndent(person, "", "  ")
    if err != nil {
        fmt.Println("Error marshaling pretty JSON:", err)
        return
    }
    
    fmt.Println("Pretty JSON:", string(prettyJSON))
}

4.1.2 JSON反序列化

go
package main

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    Name    string `json:"name"`
    Age     int    `json:"age"`
    Email   string `json:"email,omitempty"`
    Address *Address `json:"address,omitempty"`
}

type Address struct {
    City    string `json:"city"`
    Street  string `json:"street"`
    ZipCode string `json:"zip_code"`
}

func main() {
    // JSON字符串
    jsonData := `{
        "name": "John Doe",
        "age": 30,
        "email": "john@example.com",
        "address": {
            "city": "New York",
            "street": "123 Main St",
            "zip_code": "10001"
        }
    }`
    
    // 反序列化为结构体
    var person Person
    err := json.Unmarshal([]byte(jsonData), &person)
    if err != nil {
        fmt.Println("Error unmarshaling JSON:", err)
        return
    }
    
    fmt.Printf("Name: %s\n", person.Name)
    fmt.Printf("Age: %d\n", person.Age)
    fmt.Printf("Email: %s\n", person.Email)
    if person.Address != nil {
        fmt.Printf("Address: %s, %s, %s\n", person.Address.City, person.Address.Street, person.Address.ZipCode)
    }
}

4.2 XML处理

4.2.1 XML序列化

go
package main

import (
    "encoding/xml"
    "fmt"
)

type Person struct {
    XMLName xml.Name `xml:"Person"`
    Name    string   `xml:"Name"`
    Age     int      `xml:"Age"`
    Email   string   `xml:"Email,omitempty"`
    Address Address  `xml:"Address,omitempty"`
}

type Address struct {
    City    string `xml:"City"`
    Street  string `xml:"Street"`
    ZipCode string `xml:"ZipCode"`
}

func main() {
    // 创建结构体实例
    person := Person{
        Name:  "John Doe",
        Age:   30,
        Email: "john@example.com",
        Address: Address{
            City:    "New York",
            Street:  "123 Main St",
            ZipCode: "10001",
        },
    }
    
    // 序列化为XML
    xmlData, err := xml.Marshal(person)
    if err != nil {
        fmt.Println("Error marshaling XML:", err)
        return
    }
    
    fmt.Println("XML:", string(xmlData))
    
    // 美化XML
    xmlData, err = xml.MarshalIndent(person, "", "  ")
    if err != nil {
        fmt.Println("Error marshaling pretty XML:", err)
        return
    }
    
    fmt.Println("Pretty XML:", string(xmlData))
}

4.2.2 XML反序列化

go
package main

import (
    "encoding/xml"
    "fmt"
)

type Person struct {
    XMLName xml.Name `xml:"Person"`
    Name    string   `xml:"Name"`
    Age     int      `xml:"Age"`
    Email   string   `xml:"Email,omitempty"`
    Address Address  `xml:"Address,omitempty"`
}

type Address struct {
    City    string `xml:"City"`
    Street  string `xml:"Street"`
    ZipCode string `xml:"ZipCode"`
}

func main() {
    // XML字符串
    xmlData := `<?xml version="1.0" encoding="UTF-8"?>
    <Person>
        <Name>John Doe</Name>
        <Age>30</Age>
        <Email>john@example.com</Email>
        <Address>
            <City>New York</City>
            <Street>123 Main St</Street>
            <ZipCode>10001</ZipCode>
        </Address>
    </Person>`
    
    // 反序列化为结构体
    var person Person
    err := xml.Unmarshal([]byte(xmlData), &person)
    if err != nil {
        fmt.Println("Error unmarshaling XML:", err)
        return
    }
    
    fmt.Printf("Name: %s\n", person.Name)
    fmt.Printf("Age: %d\n", person.Age)
    fmt.Printf("Email: %s\n", person.Email)
    fmt.Printf("Address: %s, %s, %s\n", person.Address.City, person.Address.Street, person.Address.ZipCode)
}

5. 时间操作

5.1 时间格式化

go
package main

import (
    "fmt"
    "time"
)

func main() {
    // 获取当前时间
    now := time.Now()
    fmt.Println("Current time:", now)
    
    // 格式化时间
    fmt.Println("RFC3339:", now.Format(time.RFC3339))
    fmt.Println("ANSIC:", now.Format(time.ANSIC))
    fmt.Println("UnixDate:", now.Format(time.UnixDate))
    fmt.Println("Kitchen:", now.Format(time.Kitchen))
    
    // 自定义格式
    fmt.Println("Custom format:", now.Format("2006-01-02 15:04:05 Monday"))
    
    // 解析时间
    timeStr := "2023-12-25 10:30:00"
    parsedTime, err := time.Parse("2006-01-02 15:04:05", timeStr)
    if err != nil {
        fmt.Println("Error parsing time:", err)
        return
    }
    fmt.Println("Parsed time:", parsedTime)
}

5.2 时间计算

go
package main

import (
    "fmt"
    "time"
)

func main() {
    now := time.Now()
    fmt.Println("Current time:", now)
    
    // 时间加减
    oneHourLater := now.Add(1 * time.Hour)
    fmt.Println("One hour later:", oneHourLater)
    
    twoDaysAgo := now.Add(-2 * 24 * time.Hour)
    fmt.Println("Two days ago:", twoDaysAgo)
    
    // 时间比较
    fmt.Println("Is oneHourLater after now?", oneHourLater.After(now))
    fmt.Println("Is twoDaysAgo before now?", twoDaysAgo.Before(now))
    fmt.Println("Is now equal to now?", now.Equal(now))
    
    // 时间差
    duration := oneHourLater.Sub(now)
    fmt.Println("Duration:", duration)
    fmt.Println("Hours:", duration.Hours())
    fmt.Println("Minutes:", duration.Minutes())
    fmt.Println("Seconds:", duration.Seconds())
}

5.3 定时器

go
package main

import (
    "fmt"
    "time"
)

func main() {
    fmt.Println("Starting timer...")
    
    // 一次性定时器
    timer := time.NewTimer(2 * time.Second)
    <-timer.C
    fmt.Println("Timer fired after 2 seconds")
    
    // 周期性定时器
    ticker := time.NewTicker(1 * time.Second)
    done := make(chan bool)
    
    go func() {
        for {
            select {
            case <-ticker.C:
                fmt.Println("Ticker ticked at", time.Now().Format("15:04:05"))
            case <-done:
                return
            }
        }
    }()
    
    // 运行5秒后停止
    time.Sleep(5 * time.Second)
    done <- true
    ticker.Stop()
    fmt.Println("Ticker stopped")
}

6. 字符串操作

6.1 基本字符串操作

go
package main

import (
    "fmt"
    "strings"
)

func main() {
    str := "Hello, Go Standard Library!"
    fmt.Println("Original:", str)
    
    // 长度
    fmt.Println("Length:", len(str))
    
    // 分割
    parts := strings.Split(str, " ")
    fmt.Println("Split:", parts)
    
    // 连接
    joined := strings.Join(parts, "-")
    fmt.Println("Joined:", joined)
    
    // 替换
    replaced := strings.ReplaceAll(str, "Go", "Golang")
    fmt.Println("Replaced:", replaced)
    
    // 大小写转换
    fmt.Println("ToUpper:", strings.ToUpper(str))
    fmt.Println("ToLower:", strings.ToLower(str))
    
    // 前缀和后缀
    fmt.Println("HasPrefix 'Hello':", strings.HasPrefix(str, "Hello"))
    fmt.Println("HasSuffix 'Library!':", strings.HasSuffix(str, "Library!"))
    
    // 包含
    fmt.Println("Contains 'Standard':", strings.Contains(str, "Standard"))
    
    // 查找
    fmt.Println("Index of 'Go':", strings.Index(str, "Go"))
    fmt.Println("LastIndex of 'o':", strings.LastIndex(str, "o"))
    
    // 修剪
    strWithSpaces := "   Hello, Go!   "
    fmt.Println("Trimmed:", strings.TrimSpace(strWithSpaces))
}

6.2 字符串转换

go
package main

import (
    "fmt"
    "strconv"
)

func main() {
    // 整数转字符串
    i := 42
    str := strconv.Itoa(i)
    fmt.Println("Int to string:", str)
    
    // 字符串转整数
    str = "123"
    i, err := strconv.Atoi(str)
    if err != nil {
        fmt.Println("Error converting string to int:", err)
        return
    }
    fmt.Println("String to int:", i)
    
    // 浮点数转字符串
    f := 3.14159
    str = strconv.FormatFloat(f, 'f', 2, 64)
    fmt.Println("Float to string:", str)
    
    // 字符串转浮点数
    str = "2.71828"
    f, err = strconv.ParseFloat(str, 64)
    if err != nil {
        fmt.Println("Error converting string to float:", err)
        return
    }
    fmt.Println("String to float:", f)
    
    // 布尔值转字符串
    b := true
    str = strconv.FormatBool(b)
    fmt.Println("Bool to string:", str)
    
    // 字符串转布尔值
    str = "true"
    b, err = strconv.ParseBool(str)
    if err != nil {
        fmt.Println("Error converting string to bool:", err)
        return
    }
    fmt.Println("String to bool:", b)
}

7. 正则表达式

go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    // 编译正则表达式
    re, err := regexp.Compile(`\b\w+@\w+\.\w+\b`)
    if err != nil {
        fmt.Println("Error compiling regex:", err)
        return
    }
    
    // 测试字符串
    text := "Contact us at john@example.com or support@company.org"
    
    // 查找匹配
    fmt.Println("Contains email:", re.MatchString(text))
    
    // 查找第一个匹配
    match := re.FindString(text)
    fmt.Println("First match:", match)
    
    // 查找所有匹配
    matches := re.FindAllString(text, -1)
    fmt.Println("All matches:", matches)
    
    // 查找匹配位置
    loc := re.FindStringIndex(text)
    if loc != nil {
        fmt.Printf("Match at positions %d-%d\n", loc[0], loc[1])
    }
    
    // 替换匹配
    replaced := re.ReplaceAllString(text, "[email]")
    fmt.Println("Replaced:", replaced)
    
    // 自定义替换
    replaced = re.ReplaceAllStringFunc(text, func(m string) string {
        return "<email>" + m + "</email>"
    })
    fmt.Println("Custom replaced:", replaced)
}

8. 上下文管理

8.1 基本用法

go
package main

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

func worker(ctx context.Context, id int) {
    for {
        select {
        case <-ctx.Done():
            fmt.Printf("Worker %d: Context cancelled\n", id)
            return
        default:
            fmt.Printf("Worker %d: Working...\n", id)
            time.Sleep(500 * time.Millisecond)
        }
    }
}

func main() {
    // 创建上下文
    ctx, cancel := context.WithCancel(context.Background())
    defer cancel()
    
    // 启动工作协程
    for i := 1; i <= 3; i++ {
        go worker(ctx, i)
    }
    
    // 运行3秒后取消
    time.Sleep(3 * time.Second)
    fmt.Println("Cancelling context...")
    cancel()
    
    // 等待工作协程退出
    time.Sleep(1 * time.Second)
    fmt.Println("Main function exiting")
}

8.2 超时控制

go
package main

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

func longRunningTask(ctx context.Context) error {
    fmt.Println("Starting long running task...")
    
    // 模拟长时间操作
    for i := 1; i <= 10; i++ {
        select {
        case <-ctx.Done():
            return ctx.Err()
        default:
            fmt.Printf("Task step %d...\n", i)
            time.Sleep(1 * time.Second)
        }
    }
    
    fmt.Println("Task completed successfully")
    return nil
}

func main() {
    // 创建带超时的上下文
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()
    
    // 执行任务
    err := longRunningTask(ctx)
    if err != nil {
        fmt.Printf("Task error: %v\n", err)
    }
    
    fmt.Println("Main function exiting")
}

8.3 传递值

go
package main

import (
    "context"
    "fmt"
)

func handler(ctx context.Context) {
    // 获取上下文值
    userID, ok := ctx.Value("userID").(string)
    if ok {
        fmt.Printf("Handler: User ID is %s\n", userID)
    }
    
    // 获取嵌套上下文值
    requestID, ok := ctx.Value("requestID").(string)
    if ok {
        fmt.Printf("Handler: Request ID is %s\n", requestID)
    }
}

func main() {
    // 创建基础上下文
    ctx := context.Background()
    
    // 添加值
    ctx = context.WithValue(ctx, "userID", "12345")
    ctx = context.WithValue(ctx, "requestID", "abc-123")
    
    // 调用处理函数
    handler(ctx)
}

9. 加密功能

9.1 哈希函数

go
package main

import (
    "crypto/md5"
    "crypto/sha256"
    "fmt"
    "hex"
)

func main() {
    data := "Hello, Go!"
    
    // MD5哈希
    md5Hash := md5.Sum([]byte(data))
    fmt.Printf("MD5: %s\n", hex.EncodeToString(md5Hash[:]))
    
    // SHA-256哈希
    sha256Hash := sha256.Sum256([]byte(data))
    fmt.Printf("SHA-256: %s\n", hex.EncodeToString(sha256Hash[:]))
}

9.2 随机数生成

go
package main

import (
    "crypto/rand"
    "fmt"
    "math/big"
)

func main() {
    // 生成随机整数
    n, err := rand.Int(rand.Reader, big.NewInt(100))
    if err != nil {
        fmt.Println("Error generating random number:", err)
        return
    }
    fmt.Println("Random integer (0-99):", n.Int64())
    
    // 生成随机字节
    randomBytes := make([]byte, 16)
    _, err = rand.Read(randomBytes)
    if err != nil {
        fmt.Println("Error generating random bytes:", err)
        return
    }
    fmt.Printf("Random bytes: %x\n", randomBytes)
}

10. 测试功能

10.1 单元测试

10.1.1 基本测试

go
// 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, fmt.Errorf("division by zero")
    }
    return a / b, nil
}

// math_test.go
package math

import (
    "testing"
)

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

func TestSubtract(t *testing.T) {
    result := Subtract(5, 3)
    if result != 2 {
        t.Errorf("Subtract(5, 3) = %d; want 2", result)
    }
}

func TestMultiply(t *testing.T) {
    result := Multiply(4, 5)
    if result != 20 {
        t.Errorf("Multiply(4, 5) = %d; want 20", result)
    }
}

func TestDivide(t *testing.T) {
    // 正常情况
    result, err := Divide(10, 2)
    if err != nil {
        t.Errorf("Divide(10, 2) returned error: %v", err)
    }
    if result != 5 {
        t.Errorf("Divide(10, 2) = %d; want 5", result)
    }
    
    // 除以零
    _, err = Divide(10, 0)
    if err == nil {
        t.Error("Divide(10, 0) should have returned an error")
    }
}

10.1.2 运行测试

bash
go test ./math
go test -v ./math  # 详细输出
go test -run TestAdd ./math  # 只运行特定测试
go test ./...  # 运行所有测试

10.2 基准测试

go
// math_benchmark_test.go
package math

import (
    "testing"
)

func BenchmarkAdd(b *testing.B) {
    // 重置计时器
    b.ResetTimer()
    
    for i := 0; i < b.N; i++ {
        Add(1, 2)
    }
}

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

运行基准测试:

bash
go test -bench=. ./math
go test -bench=BenchmarkAdd ./math  # 只运行特定基准测试
go test -bench=. -benchmem ./math  # 包含内存分配信息

11. 综合实战案例

11.1 简单的Web服务器

go
package main

import (
    "encoding/json"
    "fmt"
    "log"
    "net/http"
    "os"
    "path/filepath"
    "strconv"
    "sync"
    "time"
)

// 存储结构
type Item struct {
    ID        string    `json:"id"`
    Name      string    `json:"name"`
    Price     float64   `json:"price"`
    CreatedAt time.Time `json:"created_at"`
}

// 内存存储
var (
    items      = make(map[string]Item)
    itemsMutex sync.RWMutex
    nextID     = 1
)

// 处理函数
func createItem(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodPost {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }
    
    var item Item
    if err := json.NewDecoder(r.Body).Decode(&item); err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    
    // 生成ID
    itemsMutex.Lock()
    item.ID = strconv.Itoa(nextID)
    nextID++
    item.CreatedAt = time.Now()
    items[item.ID] = item
    itemsMutex.Unlock()
    
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusCreated)
    json.NewEncoder(w).Encode(item)
}

func getItems(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodGet {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }
    
    itemsMutex.RLock()
    defer itemsMutex.RUnlock()
    
    // 转换为切片
    itemList := make([]Item, 0, len(items))
    for _, item := range items {
        itemList = append(itemList, item)
    }
    
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(itemList)
}

func getItem(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodGet {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }
    
    id := filepath.Base(r.URL.Path)
    itemsMutex.RLock()
    item, exists := items[id]
    itemsMutex.RUnlock()
    
    if !exists {
        http.Error(w, "Item not found", http.StatusNotFound)
        return
    }
    
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(item)
}

func updateItem(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodPut {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }
    
    id := filepath.Base(r.URL.Path)
    itemsMutex.Lock()
    defer itemsMutex.Unlock()
    
    item, exists := items[id]
    if !exists {
        http.Error(w, "Item not found", http.StatusNotFound)
        return
    }
    
    var updatedItem Item
    if err := json.NewDecoder(r.Body).Decode(&updatedItem); err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    
    // 更新字段
    item.Name = updatedItem.Name
    item.Price = updatedItem.Price
    items[id] = item
    
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(item)
}

func deleteItem(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodDelete {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }
    
    id := filepath.Base(r.URL.Path)
    itemsMutex.Lock()
    defer itemsMutex.Unlock()
    
    if _, exists := items[id]; !exists {
        http.Error(w, "Item not found", http.StatusNotFound)
        return
    }
    
    delete(items, id)
    w.WriteHeader(http.StatusNoContent)
}

func main() {
    // 路由
    http.HandleFunc("/items", func(w http.ResponseWriter, r *http.Request) {
        switch r.Method {
        case http.MethodGet:
            getItems(w, r)
        case http.MethodPost:
            createItem(w, r)
        default:
            http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        }
    })
    
    http.HandleFunc("/items/", func(w http.ResponseWriter, r *http.Request) {
        switch r.Method {
        case http.MethodGet:
            getItem(w, r)
        case http.MethodPut:
            updateItem(w, r)
        case http.MethodDelete:
            deleteItem(w, r)
        default:
            http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        }
    })
    
    // 静态文件
    http.Handle("/", http.FileServer(http.Dir("./static")))
    
    // 获取端口
    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
    }
    
    fmt.Printf("Server starting on port %s...\n", port)
    log.Fatal(http.ListenAndServe(":"+port, nil))
}

11.2 命令行工具

go
package main

import (
    "bufio"
    "fmt"
    "io/ioutil"
    "os"
    "path/filepath"
    "strings"
    "flag"
)

func main() {
    // 命令行参数
    var (
        extension = flag.String("ext", ".txt", "File extension to search for")
        recursive = flag.Bool("r", false, "Recursive search")
        count     = flag.Bool("c", false, "Count files only")
        output    = flag.String("o", "", "Output file")
    )
    
    flag.Parse()
    
    // 获取搜索目录
    dirs := flag.Args()
    if len(dirs) == 0 {
        dirs = []string{"."}
    }
    
    // 搜索文件
    var foundFiles []string
    for _, dir := range dirs {
        files, err := findFiles(dir, *extension, *recursive)
        if err != nil {
            fmt.Fprintf(os.Stderr, "Error searching %s: %v\n", dir, err)
            continue
        }
        foundFiles = append(foundFiles, files...)
    }
    
    // 处理结果
    if *count {
        fmt.Printf("Found %d files with extension %s\n", len(foundFiles), *extension)
    } else {
        if *output != "" {
            // 写入文件
            err := writeResults(*output, foundFiles)
            if err != nil {
                fmt.Fprintf(os.Stderr, "Error writing output: %v\n", err)
                return
            }
            fmt.Printf("Results written to %s\n", *output)
        } else {
            // 打印到控制台
            for _, file := range foundFiles {
                fmt.Println(file)
            }
            fmt.Printf("Total: %d files\n", len(foundFiles))
        }
    }
}

func findFiles(dir, ext string, recursive bool) ([]string, error) {
    var files []string
    
    if recursive {
        err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
            if err != nil {
                return err
            }
            if !info.IsDir() && strings.HasSuffix(path, ext) {
                files = append(files, path)
            }
            return nil
        })
        if err != nil {
            return nil, err
        }
    } else {
        entries, err := ioutil.ReadDir(dir)
        if err != nil {
            return nil, err
        }
        for _, entry := range entries {
            if !entry.IsDir() && strings.HasSuffix(entry.Name(), ext) {
                files = append(files, filepath.Join(dir, entry.Name()))
            }
        }
    }
    
    return files, nil
}

func writeResults(filename string, files []string) error {
    file, err := os.Create(filename)
    if err != nil {
        return err
    }
    defer file.Close()
    
    writer := bufio.NewWriter(file)
    defer writer.Flush()
    
    for _, f := range files {
        fmt.Fprintln(writer, f)
    }
    
    return nil
}

12. 最佳实践

12.1 代码组织

  1. 模块化设计:将功能分解为独立的包和模块
  2. 清晰的命名:使用有意义的包名、函数名和变量名
  3. 错误处理:正确处理和传递错误
  4. 文档注释:为公共API添加详细的文档注释
  5. 测试覆盖:为代码编写单元测试

12.2 性能优化

  1. 避免不必要的分配:重用变量和缓冲区
  2. 使用适当的数据结构:根据场景选择合适的数据结构
  3. 减少锁竞争:使用细粒度锁或无锁数据结构
  4. I/O优化:使用缓冲I/O,批量操作
  5. 避免反射:反射操作较慢,尽量避免使用

12.3 安全性

  1. 输入验证:验证所有用户输入
  2. 错误处理:不要在错误消息中泄露敏感信息
  3. 资源管理:确保资源正确释放
  4. 并发安全:确保并发操作的安全性
  5. 避免缓冲区溢出:正确处理缓冲区大小

12.4 标准库使用技巧

  1. 查阅文档:熟悉标准库的功能和用法
  2. 使用上下文:在需要取消和超时控制的场景中使用context
  3. 使用同步原语:正确使用sync包中的同步原语
  4. 序列化选择:根据场景选择合适的序列化格式
  5. 网络编程:使用net/http包构建Web服务

13. 总结

本课程介绍了Go语言标准库的核心功能和应用场景,包括:

  1. 文件操作:创建、读写、遍历文件和目录
  2. 网络编程:HTTP服务器和客户端、TCP通信
  3. 数据序列化:JSON、XML处理
  4. 时间操作:时间格式化、计算、定时器
  5. 字符串操作:字符串处理、转换
  6. 正则表达式:字符串匹配、替换
  7. 上下文管理:取消信号、超时控制、值传递
  8. 加密功能:哈希函数、随机数生成
  9. 测试功能:单元测试、基准测试
  10. 综合实战:Web服务器、命令行工具

通过本课程的学习,你已经掌握了Go语言标准库的常用功能,可以在实际项目中灵活应用这些功能来构建高效、可靠的Go应用程序。标准库是Go语言的强大武器,熟练掌握它将大大提高你的开发效率和代码质量。

评论区

专业的Linux技术学习平台,从入门到精通的完整学习路径