← 返回首页

常用标准库

Go 语言标准库功能丰富,覆盖了网络、文件、加密、文本处理等常用场景。

📝

fmt

格式化 I/O

🌐

net/http

HTTP 服务与客户端

🔄

encoding/json

JSON 序列化

📅

time

时间处理

🔍

regexp

正则表达式

🔒

crypto

加密功能

regexp 正则表达式

基础匹配

package main

import (
    "fmt"
    "regexp"
)

func main() {
    // 编译正则表达式
    re := regexp.MustCompile(`Hello`)
    
    // 匹配字符串
    text := "Hello, World!"
    matched := re.MatchString(text)
    fmt.Println("Matched:", matched)
    
    // 查找匹配
    loc := re.FindStringIndex(text)
    fmt.Println("Location:", loc)
}

捕获组

package main

import (
    "fmt"
    "regexp"
)

func main() {
    // 使用捕获组
    re := regexp.MustCompile(`(\w+)\s+(\w+)`)
    
    text := "Hello World"
    matches := re.FindStringSubmatch(text)
    
    fmt.Println("Full match:", matches[0])
    fmt.Println("Group 1:", matches[1])
    fmt.Println("Group 2:", matches[2])
}

替换

package main

import (
    "fmt"
    "regexp"
)

func main() {
    // 简单替换
    re := regexp.MustCompile(`Hello`)
    result := re.ReplaceAllString("Hello World", "Hi")
    fmt.Println(result)
    
    // 使用捕获组替换
    re2 := regexp.MustCompile(`(\w+)\s+(\w+)`)
    result2 := re2.ReplaceAllString("Hello World", "$2 $1")
    fmt.Println(result2)
    
    // 使用函数替换
    result3 := re2.ReplaceAllStringFunc("Hello World", func(s string) string {
        return "REPLACED"
    })
    fmt.Println(result3)
}

查找所有匹配

package main

import (
    "fmt"
    "regexp"
)

func main() {
    // 查找所有匹配
    re := regexp.MustCompile(`\d+`)
    text := "I have 2 apples and 3 oranges"
    
    matches := re.FindAllString(text, -1)
    fmt.Println("All matches:", matches)
    
    // 查找所有匹配及其位置
    matchesWithPos := re.FindAllStringIndex(text, -1)
    fmt.Println("Matches with positions:", matchesWithPos)
    
    // 查找所有子匹配
    re2 := regexp.MustCompile(`(\w+)\s+(\w+)`)
    submatches := re2.FindAllStringSubmatch(text, -1)
    fmt.Println("Submatches:", submatches)
}

常用正则表达式

package main

import (
    "fmt"
    "regexp"
)

func main() {
    // 验证邮箱
    emailRe := regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`)
    fmt.Println("Valid email:", emailRe.MatchString("user@example.com"))
    
    // 验证 URL
    urlRe := regexp.MustCompile(`^https?://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}`)
    fmt.Println("Valid URL:", urlRe.MatchString("https://example.com"))
    
    // 验证手机号(中国)
    phoneRe := regexp.MustCompile(`^1[3-9]\d{9}$`)
    fmt.Println("Valid phone:", phoneRe.MatchString("13800138000"))
    
    // 提取 HTML 标签内容
    htmlRe := regexp.MustCompile(`<[^>]+>([^<]+)]+>`)
    html := "

Hello

World
"
tags := htmlRe.FindAllStringSubmatch(html, -1) for _, tag := range tags { fmt.Println("Tag content:", tag[1]) } }

sync 并发原语

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() {
    var counter Counter
    var wg sync.WaitGroup
    
    for i := 0; i < 1000; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            counter.Increment()
        }()
    }
    
    wg.Wait()
    fmt.Println("Final value:", counter.Value())
}

RWMutex 读写锁

package main

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

type Cache struct {
    mu    sync.RWMutex
    data  map[string]string
}

func NewCache() *Cache {
    return &Cache{
        data: make(map[string]string),
    }
}

func (c *Cache) Get(key string) (string, bool) {
    c.mu.RLock()
    defer c.mu.RUnlock()
    val, ok := c.data[key]
    return val, ok
}

func (c *Cache) Set(key, value string) {
    c.mu.Lock()
    defer c.mu.Unlock()
    c.data[key] = value
}

func main() {
    cache := NewCache()
    var wg sync.WaitGroup
    
    // 写入
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(i int) {
            defer wg.Done()
            key := fmt.Sprintf("key%d", i)
            value := fmt.Sprintf("value%d", i)
            cache.Set(key, value)
        }(i)
    }
    
    // 读取
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(i int) {
            defer wg.Done()
            key := fmt.Sprintf("key%d", i)
            time.Sleep(time.Millisecond)
            val, ok := cache.Get(key)
            fmt.Printf("Get %s: %v, %v\n", key, val, ok)
        }(i)
    }
    
    wg.Wait()
}

WaitGroup 等待组

package main

import (
    "fmt"
    "sync"
)

func worker(id int, wg *sync.WaitGroup) {
    defer wg.Done()
    fmt.Printf("Worker %d started\n", id)
    fmt.Printf("Worker %d finished\n", id)
}

func main() {
    var wg sync.WaitGroup
    
    for i := 1; i <= 5; i++ {
        wg.Add(1)
        go worker(i, &wg)
    }
    
    wg.Wait()
    fmt.Println("All workers finished")
}

Once 单次执行

package main

import (
    "fmt"
    "sync"
)

var (
    once     sync.Once
    instance *Singleton
)

type Singleton struct {
    value string
}

func GetInstance() *Singleton {
    once.Do(func() {
        instance = &Singleton{value: "initialized"}
        fmt.Println("Singleton initialized")
    })
    return instance
}

func main() {
    // 多次调用只会初始化一次
    GetInstance()
    GetInstance()
    GetInstance()
}

Cond 条件变量

package main

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

func main() {
    var mu sync.Mutex
    cond := sync.NewCond(&mu)
    ready := false
    
    // 等待者
    go func() {
        mu.Lock()
        for !ready {
            fmt.Println("Waiting...")
            cond.Wait()
        }
        fmt.Println("Ready!")
        mu.Unlock()
    }()
    
    time.Sleep(time.Second)
    
    // 通知者
    mu.Lock()
    ready = true
    fmt.Println("Signaling...")
    cond.Signal()
    mu.Unlock()
    
    time.Sleep(time.Second)
}

Pool 对象池

package main

import (
    "bytes"
    "fmt"
    "sync"
)

var bufferPool = sync.Pool{
    New: func() interface{} {
        fmt.Println("Creating new buffer")
        return &bytes.Buffer{}
    },
}

func process() {
    // 从池中获取
    buf := bufferPool.Get().(*bytes.Buffer)
    defer func() {
        // 重置并放回池中
        buf.Reset()
        bufferPool.Put(buf)
    }()
    
    buf.WriteString("Hello, World!")
    fmt.Println("Buffer:", buf.String())
}

func main() {
    for i := 0; i < 5; i++ {
        process()
    }
}

Map 并发安全映射

package main

import (
    "fmt"
    "sync"
)

func main() {
    var m sync.Map
    
    // 存储
    m.Store("key1", "value1")
    m.Store("key2", "value2")
    
    // 加载
    if val, ok := m.Load("key1"); ok {
        fmt.Println("key1:", val)
    }
    
    // 加载或存储
    actual, loaded := m.LoadOrStore("key3", "value3")
    fmt.Printf("key3: %v, loaded: %v\n", actual, loaded)
    
    // 遍历
    m.Range(func(key, value interface{}) bool {
        fmt.Printf("%s: %s\n", key, value)
        return true
    })
    
    // 删除
    m.Delete("key1")
}

Atomic 原子操作

package main

import (
    "fmt"
    "sync/atomic"
)

func main() {
    var counter int64
    
    // 原子增加
    atomic.AddInt64(&counter, 1)
    fmt.Println("Counter:", counter)
    
    // 原子加载
    value := atomic.LoadInt64(&counter)
    fmt.Println("Loaded:", value)
    
    // 原子存储
    atomic.StoreInt64(&counter, 100)
    fmt.Println("Stored:", atomic.LoadInt64(&counter))
    
    // 原子比较并交换
    swapped := atomic.CompareAndSwapInt64(&counter, 100, 200)
    fmt.Printf("Swapped: %v, Value: %d\n", swapped, atomic.LoadInt64(&counter))
}

json 数据编码

基本编码和解码

package main

import (
    "encoding/json"
    "fmt"
)

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

func main() {
    // 编码
    person := Person{
        Name: "Alice",
        Age:  30,
    }
    
    jsonData, err := json.Marshal(person)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println("JSON:", string(jsonData))
    
    // 解码
    var decoded Person
    err = json.Unmarshal(jsonData, &decoded)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Printf("Decoded: %+v\n", decoded)
}

处理嵌套结构

package main

import (
    "encoding/json"
    "fmt"
)

type Address struct {
    City    string `json:"city"`
    Country string `json:"country"`
}

type User struct {
    Name    string  `json:"name"`
    Age     int     `json:"age"`
    Address Address  `json:"address"`
    Tags    []string `json:"tags"`
}

func main() {
    jsonData := []byte(`{
        "name": "Bob",
        "age": 25,
        "address": {
            "city": "Beijing",
            "country": "China"
        },
        "tags": ["developer", "golang"]
    }`)
    
    var user User
    err := json.Unmarshal(jsonData, &user)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    fmt.Printf("User: %+v\n", user)
    fmt.Printf("Address: %+v\n", user.Address)
    fmt.Printf("Tags: %v\n", user.Tags)
}

使用 map 和 interface

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    // 解码到 map
    jsonData := []byte(`{"name": "Charlie", "age": 35}`)
    var data map[string]interface{}, ok := m.data[key]
    return val, ok
}

func (c *Cache) Set(key, value string) {
    c.mu.Lock()
    defer c.mu.Unlock()
    c.data[key] = value
}

func main() {
    cache := NewCache()
    var wg sync.WaitGroup
    
    // 写入
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(i int) {
            defer wg.Done()
            key := fmt.Sprintf("key%d", i)
            value := fmt.Sprintf("value%d", i)
            cache.Set(key, value)
        }(i)
    }
    
    // 读取
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(i int) {
            defer wg.Done()
            key := fmt.Sprintf("key%d", i)
            time.Sleep(time.Millisecond)
            val, ok := cache.Get(key)
            fmt.Printf("Get %s: %v, %v\n", key, val, ok)
        }(i)
    }
    
    wg.Wait()
}

WaitGroup 等待组

package main

import (
    "fmt"
    "sync"
)

func worker(id int, wg *sync.WaitGroup) {
    defer wg.Done()
    fmt.Printf("Worker %d started\n", id)
    fmt.Printf("Worker %d finished\n", id)
}

func main() {
    var wg sync.WaitGroup
    
    for i := 1; i <= 5; i++ {
        wg.Add(1)
        go worker(i, &wg)
    }
    
    wg.Wait()
    fmt.Println("All workers finished")
}

Once 单次执行

package main

import (
    "fmt"
    "sync"
)

var (
    once     sync.Once
    instance *Singleton
)

type Singleton struct {
    value string
}

func GetInstance() *Singleton {
    once.Do(func() {
        instance = &Singleton{value: "initialized"}
        fmt.Println("Singleton initialized")
    })
    return instance
}

func main() {
    // 多次调用只会初始化一次
    GetInstance()
    GetInstance()
    GetInstance()
}

Cond 条件变量

package main

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

func main() {
    var mu sync.Mutex
    cond := sync.NewCond(&mu)
    ready := false
    
    // 等待者
    go func() {
        mu.Lock()
        for !ready {
            fmt.Println("Waiting...")
            cond.Wait()
        }
        fmt.Println("Ready!")
        mu.Unlock()
    }()
    
    time.Sleep(time.Second)
    
    // 通知者
    mu.Lock()
    ready = true
    fmt.Println("Signaling...")
    cond.Signal()
    mu.Unlock()
    
    time.Sleep(time.Second)
}

Pool 对象池

package main

import (
    "bytes"
    "fmt"
    "sync"
)

var bufferPool = sync.Pool{
    New: func() interface{} {
        fmt.Println("Creating new buffer")
        return &bytes.Buffer{}
    },
}

func process() {
    // 从池中获取
    buf := bufferPool.Get().(*bytes.Buffer)
    defer func() {
        // 重置并放回池中
        buf.Reset()
        bufferPool.Put(buf)
    }()
    
    buf.WriteString("Hello, World!")
    fmt.Println("Buffer:", buf.String())
}

func main() {
    for i := 0; i < 5; i++ {
        process()
    }
}

Map 并发安全映射

package main

import (
    "fmt"
    "sync"
)

func main() {
    var m sync.Map
    
    // 存储
    m.Store("key1", "value1")
    m.Store("key2", "value2")
    
    // 加载
    if val, ok := m.Load("key1"); ok {
        fmt.Println("key1:", val)
    }
    
    // 加载或存储
    actual, loaded := m.LoadOrStore("key3", "value3")
    fmt.Printf("key3: %v, loaded: %v\n", actual, loaded)
    
    // 遍历
    m.Range(func(key, value interface{}) bool {
        fmt.Printf("%s: %s\n", key, value)
        return true
    })
    
    // 删除
    m.Delete("key1")
}

Atomic 原子操作

package main

import (
    "fmt"
    "sync/atomic"
)

func main() {
    var counter int64
    
    // 原子增加
    atomic.AddInt64(&counter, 1)
    fmt.Println("Counter:", counter)
    
    // 原子加载
    value := atomic.LoadInt64(&counter)
    fmt.Println("Loaded:", value)
    
    // 原子存储
    atomic.StoreInt64(&counter, 100)
    fmt.Println("Stored:", atomic.LoadInt64(&counter))
    
    // 原子比较并交换
    swapped := atomic.CompareAndSwapInt64(&counter, 100, 200)
    fmt.Printf("Swapped: %v, Value: %d\n", swapped, atomic.LoadInt64(&counter))
}

json 数据编码

基本编码和解码

package main

import (
    "encoding/json"
    "fmt"
)

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

func main() {
    // 编码
    person := Person{
        Name: "Alice",
        Age:  30,
    }
    
    jsonData, err := json.Marshal(person)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println("JSON:", string(jsonData))
    
    // 解码
    var decoded Person
    err = json.Unmarshal(jsonData, &decoded)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Printf("Decoded: %+v\n", decoded)
}

处理嵌套结构

package main

import (
    "encoding/json"
    "fmt"
)

type Address struct {
    City    string `json:"city"`
    Country string `json:"country"`
}

type User struct {
    Name    string  `json:"name"`
    Age     int     `json:"age"`
    Address Address  `json:"address"`
    Tags    []string `json:"tags"`
}

func main() {
    jsonData := []byte(`{
        "name": "Bob",
        "age": 25,
        "address": {
            "city": "Beijing",
            "country": "China"
        },
        "tags": ["developer", "golang"]
    }`)
    
    var user User
    err := json.Unmarshal(jsonData, &user)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    fmt.Printf("User: %+v\n", user)
    fmt.Printf("Address: %+v\n", user.Address)
    fmt.Printf("Tags: %v\n", user.Tags)
}

使用 map 和 interface

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    // 解码到 map
    jsonData := []byte(`{"name": "Charlie", "age": 35}`)
    var data map[string]interface{
    
    err := json.Unmarshal(jsonData, &data)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    fmt.Printf("Name: %v\n", data["name"])
    fmt.Printf("Age: %v\n", data["age"])
    
    // 编码 map
    newMap := map[string]interface{
        "key1": "value1",
        "key2": 123,
        "key3": true,
    }
    
    result, err := json.Marshal(newMap)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println("Map JSON:", string(result))
}

JSON 流式处理

package main

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

type Item struct {
    ID   int    `json:"id"`
    Name string `json:"name"`
}

func main() {
    // JSON 数组流
    jsonStream := `[{"id":1,"name":"Item1"},{"id":2,"name":"Item2"}]`
    
    decoder := json.NewDecoder(strings.NewReader(jsonStream))
    
    // 读取开始数组标记
    t, err := decoder.Token()
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println("Start token:", t)
    
    // 读取数组元素
    for decoder.More() {
        var item Item
        err := decoder.Decode(&item)
        if err != nil {
            fmt.Println("Error:", err)
            return
        }
        fmt.Printf("Item: %+v\n", item)
    }
    
    // 读取结束数组标记
    t, err = decoder.Token()
    fmt.Println("End token:", t)
}

自定义 JSON 编码

package main

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

type CustomTime struct {
    time.Time
}

const customTimeFormat = "2006-01-02 15:04:05"

func (ct *CustomTime) UnmarshalJSON(data []byte) error {
    var s string
    if err := json.Unmarshal(data, &s); err != nil {
        return err
    }
    
    t, err := time.Parse(customTimeFormat, s)
    if err != nil {
        return err
    }
    
    ct.Time = t
    return nil
}

func (ct CustomTime) MarshalJSON() ([]byte, error) {
    return json.Marshal(ct.Format(customTimeFormat))
}

type Event struct {
    Name string     `json:"name"`
    Time CustomTime `json:"time"`
}

func main() {
    event := Event{
        Name: "Meeting",
        Time: CustomTime{time.Now()},
    }
    
    jsonData, _ := json.Marshal(event)
    fmt.Println("Custom JSON:", string(jsonData))
    
    var decoded Event
    json.Unmarshal(jsonData, &decoded)
    fmt.Printf("Decoded: %+v\n", decoded)
}

错误处理

package main

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

type User struct {
    Name string `json:"name"`
    Age  int    json:"age,required"
}

func main() {
    // 无效 JSON
    jsonData := []byte(`{"name": "Test"}`)
    
    var user User
    err := json.Unmarshal(jsonData, &user)
    if err != nil {
        fmt.Println("Unmarshal error:", err)
        
        var syntaxErr *json.SyntaxError
        if errors.As(err, &syntaxErr) {
            fmt.Printf("Syntax error at offset %d\n", syntaxErr.Offset)
        }
        
        var unmarshalErr *json.UnmarshalTypeError
        if errors.As(err, &unmarshalErr) {
            fmt.Printf("Type error: expected %s, got %s\n", 
                unmarshalErr.Type, unmarshalErr.Value)
        }
    }
}

time 时间处理

获取当前时间

package main

import (
    "fmt"
    "time"
)

func main() {
    // 获取当前时间
    now := time.Now()
    fmt.Println("Current time:", now)
    
    // 获取 UTC 时间
    utc := time.Now().UTC()
    fmt.Println("UTC time:", utc)
}

时间格式化

package main

import (
    "fmt"
    "time"
)

func main() {
    now := time.Now()
    
    // 使用预定义格式
    fmt.Println("RFC3339:", now.Format(time.RFC3339))
    fmt.Println("RFC1123:", now.Format(time.RFC1123))
    
    // 自定义格式(参考 2006-01-02 15:04:05)
    fmt.Println("Custom:", now.Format("2006-01-02 15:04:05"))
    fmt.Println("Date only:", now.Format("2006-01-02"))
    fmt.Println("Time only:", now.Format("15:04:05"))
}

时间解析

package main

import (
    "fmt"
    "time"
)

func main() {
    // 解析时间字符串
    timeStr := "2024-01-26 15:30:45"
    parsedTime, err := time.Parse("2006-01-02 15:04:05", timeStr)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println("Parsed time:", parsedTime)
    
    // 解析 RFC3339 格式
    rfcTime, err := time.Parse(time.RFC3339, "2024-01-26T15:30:45Z")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println("RFC3339 time:", rfcTime)
}

时间计算

package main

import (
    "fmt"
    "time"
)

func main() {
    now := time.Now()
    
    // 添加时间
    future := now.Add(24 * time.Hour)
    fmt.Println("24 hours later:", future)
    
    // 减去时间
    past := now.Add(-24 * time.Hour)
    fmt.Println("24 hours ago:", past)
    
    // 计算时间差
    duration := future.Sub(now)
    fmt.Println("Duration:", duration)
    fmt.Println("Hours:", duration.Hours())
    fmt.Println("Minutes:", duration.Minutes())
    
    // 计算两个时间之间的天数
    days := duration.Hours() / 24
    fmt.Println("Days:", days)
}

定时器和 Ticker

package main

import (
    "fmt"
    "time"
)

func main() {
    // Timer:一次性定时器
    timer := time.NewTimer(2 * time.Second)
    <-timer.C
    fmt.Println("Timer expired")
    
    // Ticker:周期性定时器
    ticker := time.NewTicker(1 * time.Second)
    defer ticker.Stop()
    
    for i := 0; i < 3; i++ {
        <-ticker.C
        fmt.Printf("Tick %d\n", i)
    }
}

时区处理

package main

import (
    "fmt"
    "time"
)

func main() {
    // 加载时区
    loc, err := time.LoadLocation("Asia/Shanghai")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    // 在指定时区创建时间
    now := time.Now().In(loc)
    fmt.Println("Shanghai time:", now)
    
    // 转换时区
    nyLoc, _ := time.LoadLocation("America/New_York")
    nyTime := now.In(nyLoc)
    fmt.Println("New York time:", nyTime)
}

io 输入输出

读取文件

package main

import (
    "fmt"
    "io"
    "os"
)

func main() {
    // 打开文件
    file, err := os.Open("test.txt")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer file.Close()
    
    // 读取整个文件
    data, err := io.ReadAll(file)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println("File content:", string(data))
}

写入文件

package main

import (
    "fmt"
    "os"
)

func main() {
    // 写入文件(覆盖)
    err := os.WriteFile("output.txt", []byte("Hello, World!"), 0644)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    // 追加写入
    f, err := os.OpenFile("output.txt", os.O_APPEND|os.O_WRONLY, 0644)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer f.Close()
    
    _, err = f.WriteString("\nAppended text")
    if err != nil {
        fmt.Println("Error:", err)
    }
}

读取目录

package main

import (
    "fmt"
    "os"
)

func main() {
    // 读取目录内容
    entries, err := os.ReadDir(".")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    for _, entry := range entries {
        fmt.Printf("%s (%v)\n", entry.Name(), entry.IsDir())
    }
}

创建和删除文件/目录

package main

import (
    "fmt"
    "os"
)

func main() {
    // 创建目录
    err := os.MkdirAll("testdir/subdir", 0755)
    if err != nil {
        fmt.Println("Error:", err)
    }
    
    // 创建文件
    file, err := os.Create("testdir/test.txt")
    if err != nil {
        fmt.Println("Error:", err)
    }
    file.Close()
    
    // 删除文件
    os.Remove("testdir/test.txt")
    
    // 删除目录
    os.RemoveAll("testdir")
}

使用 io.Copy

package main

import (
    "io"
    "os"
)

func copyFile(src, dst string) error {
    source, err := os.Open(src)
    if err != nil {
        return err
    }
    defer source.Close()
    
    destination, err := os.Create(dst)
    if err != nil {
        return err
    }
    defer destination.Close()
    
    _, err = io.Copy(destination, source)
    return err
}

使用 io.LimitReader

package main

import (
    "fmt"
    "io"
    "strings"
)

func main() {
    reader := strings.NewReader("Hello, World! This is a long string.")
    
    // 限制读取 5 个字节
    limitedReader := io.LimitReader(reader, 5)
    
    data, _ := io.ReadAll(limitedReader)
    fmt.Println("Limited read:", string(data))
}

bufio 缓冲 I/O

缓冲读取

package main

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

func main() {
    file, _ := os.Open("test.txt")
    defer file.Close()
    
    scanner := bufio.NewScanner(file)
    
    // 逐行读取
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }
}

缓冲写入

package main

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

func main() {
    file, _ := os.Create("output.txt")
    defer file.Close()
    
    writer := bufio.NewWriter(file)
    defer writer.Flush()
    
    for i := 0; i < 10; i++ {
        fmt.Fprintln(writer, "Line", i)
    }
}

从标准输入读取

package main

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

func main() {
    scanner := bufio.NewScanner(os.Stdin)
    
    fmt.Print("Enter your name: ")
    scanner.Scan()
    name := scanner.Text()
    
    fmt.Printf("Hello, %s!\n", name)
}

读取分隔符

package main

import (
    "bufio"
    "fmt"
    "strings"
)

func main() {
    reader := strings.NewReader("apple,banana,cherry")
    scanner := bufio.NewScanner(reader)
    
    // 设置分隔符
    scanner.Split(bufio.ScanWords)
    
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }
}

使用 bufio.Reader

package main

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

func main() {
    file, _ := os.Open("test.txt")
    defer file.Close()
    
    reader := bufio.NewReader(file)
    
    // 读取到分隔符
    line, _ := reader.ReadString('\n')
    fmt.Println("Line:", line)
    
    // 读取字节
    data := make([]byte, 10)
    n, _ := reader.Read(data)
    fmt.Printf("Read %d bytes: %s\n", n, data)
}

使用 bufio.Writer

package main

import (
    "bufio"
    "os"
)

func main() {
    file, _ := os.Create("output.txt")
    defer file.Close()
    
    writer := bufio.NewWriter(file)
    
    // 写入字节
    writer.Write([]byte("Hello"))
    
    // 写入字符串
    writer.WriteString(", World!")
    
    // 刷新缓冲区
    writer.Flush()
}

Embed 简介

embed 是 Go 1.16 引入的标准库,用于在编译时将文件嵌入到 Go 程序中。它提供了一种简单、类型安全的方式来访问嵌入的文件,无需在运行时读取文件系统。

Embed 的核心特性

  • 编译时嵌入:文件在编译时被嵌入到二进制文件中
  • 类型安全:提供 string、[]byte 和 fs.FS 类型
  • 跨平台:自动处理不同操作系统的路径分隔符
  • 零依赖:不需要额外的依赖管理
  • 简单易用:通过 //go:embed 指令声明

最佳实践

regexp 最佳实践

package main

import (
    "regexp"
    "sync"
)

// 1. 预编译正则表达式
var (
    emailRe     = regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`)
    phoneRe     = regexp.MustCompile(`^1[3-9]\d{9}$`)
    reCache     = make(map[string]*regexp.Regexp)
    reCacheMu   sync.RWMutex
)

// 2. 缓存正则表达式
func GetRegex(pattern string) (*regexp.Regexp, error) {
    reCacheMu.RLock()
    re, ok := reCache[pattern]
    reCacheMu.RUnlock()
    
    if ok {
        return re, nil
    }
    
    re, err := regexp.Compile(pattern)
    if err != nil {
        return nil, err
    }
    
    reCacheMu.Lock()
    reCache[pattern] = re
    reCacheMu.Unlock()
    
    return re, nil
}

// 3. 使用原始字符串避免转义
// 好:`\d+`
// 坏:"\d+"

// 4. 避免贪婪匹配
// 好:`<.*?>`
// 坏:`<.*>`

// 5. 使用非捕获组
// 好:`(?:a|b)c`
// 坏:`(a|b)c`

sync 最佳实践

package main

import (
    "sync"
)

// 1. 避免锁的嵌套
type SafeCounter struct {
    mu    sync.Mutex
    value int
}

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

// 2. 使用 defer 确保锁释放
func (c *SafeCounter) Get() int {
    c.mu.Lock()
    defer c.mu.Unlock()
    return c.value
}

// 3. 读写锁用于读多写少场景
type SafeMap struct {
    mu   sync.RWMutex
    data map[string]string
}

func (m *SafeMap) Get(key string) (string, bool) {
    m.mu.RLock()
    defer m.mu.RUnlock()
    val, ok := m.data[key]
    return val, ok
}

func (m *SafeMap) Set(key, value string) {
    m.mu.Lock()
    defer m.mu.Unlock()
    m.data[key] = value
}

// 4. 使用 sync.Pool 重用对象
var bufferPool = sync.Pool{
    New: func() interface{} {
        return make([]byte, 0, 1024)
    },
}

func getBuffer() []byte {
    return bufferPool.Get().([]byte)
}

func putBuffer(buf []byte) {
    bufferPool.Put(buf[:0])
}

// 5. 使用 sync.Map 替代 map+Mutex(特定场景)
// 适用于:读多写少、键值对稳定

json 最佳实践

package main

import (
    "encoding/json"
)

// 1. 使用结构体标签
type User struct {
    Name     string `json:"name"`
    Age      int    `json:"age"`
    Password string json:"-"`           // 忽略
    Email    string `json:"email,omitempty"` // 空值忽略
}

// 2. 使用指针处理可选字段
type Config struct {
    Timeout *int  `json:"timeout,omitempty"`
    Enabled *bool `json:"enabled,omitempty"`
}

// 3. 使用 json.RawMessage 延迟解析
type Message struct {
    Type    string          `json:"type"`
    Payload json.RawMessage `json:"payload"`
}

// 4. 使用 json.Number 处理大数字
type Data struct {
    ID json.Number `json:"id"`
}

// 5. 验证 JSON 结构
func validateJSON(data []byte) bool {
    var v interface{
    return json.Valid(data)
}

// 6. 使用 json.Encoder/Decoder 处理流
// 适用于大文件或网络流

// 7. 处理自定义时间格式
type CustomTime struct {
    time.Time
}

func (ct *CustomTime) UnmarshalJSON(b []byte) error {
    s := string(b)
    t, err := time.Parse("2006-01-02", s)
    if err != nil {
        return err
    }
    ct.Time = t
    return nil
}

exp 实验性标准库

简介

exp(experimental)是 Go 语言的实验性标准库,包含了一些新功能和实验性的实现。这些库可能会在未来成为标准库的一部分,也可能被移除或修改。常用的 exp 库包括 expvar(变量监控)、slog(结构化日志)等。

expvar 变量监控

expvar 提供了一种标准化的方式来发布和监控运行时的变量,特别适合用于监控和调试。

基本使用

package main

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

var (
    requests    = expvar.NewInt("requests")
    errors      = expvar.NewInt("errors")
    connections = expvar.NewInt("connections")
)

func main() {
    // 注册 HTTP 处理器
    http.Handle("/debug/vars", expvar.Handler())
    
    // 模拟请求处理
    go func() {
        for {
            requests.Add(1)
            time.Sleep(time.Second)
        }
    }()
    
    fmt.Println("Server started on :8080")
    fmt.Println("Visit http://localhost:8080/debug/vars to see metrics")
    http.ListenAndServe(":8080", nil)
}

自定义变量

package main

import (
    "expvar"
    "fmt"
    "sync"
)

// 自定义计数器
type Counter struct {
    mu    sync.Mutex
    count int
}

func (c *Counter) String() string {
    c.mu.Lock()
    defer c.mu.Unlock()
    return fmt.Sprintf("%d", c.count)
}

func (c *Counter) Add(n int) {
    c.mu.Lock()
    defer c.mu.Unlock()
    c.count += n
}

var customCounter = &Counter{}

func init() {
    expvar.Publish("custom_counter", customCounter)
}

func main() {
    customCounter.Add(1)
    customCounter.Add(2)
    
    // 获取变量值
    val := expvar.Get("custom_counter")
    fmt.Println("Custom counter:", val.String())
}

Map 类型

package main

import (
    "expvar"
    "fmt"
)

var (
    // 创建 Map
    stats = expvar.NewMap("stats")
)

func main() {
    // 添加键值对
    stats.Add("requests", 100)
    stats.Add("errors", 5)
    
    // 设置值
    stats.Set("version", expvar.String("1.0.0"))
    
    // 获取值
    requests := stats.Get("requests")
    fmt.Println("Requests:", requests.String())
    
    // 遍历所有键
    stats.Do(func(kv expvar.KeyValue) bool {
        fmt.Printf("%s: %s\n", kv.Key, kv.Value.String())
        return true
    })
}

Float 类型

var (
    cpuUsage = expvar.NewFloat("cpu_usage")
    memory   = expvar.NewFloat("memory_usage")
)

func updateMetrics() {
    cpuUsage.Set(45.5)
    memory.Set(1024.5)
}

String 类型

var (
    version   = expvar.NewString("version")
    buildTime = expvar.NewString("build_time")
)

func init() {
    version.Set("1.0.0")
    buildTime.Set("2024-01-01 00:00:00")
}

在 Web 服务器中使用

package main

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

var (
    requestCount = expvar.NewInt("request_count")
    errors       = expvar.NewInt("errors")
    avgTime      = expvar.NewFloat("avg_time_ms")
)

func handler(w http.ResponseWriter, r *http.Request) {
    start := time.Now()
    
    requestCount.Add(1)
    
    // 模拟处理
    time.Sleep(time.Millisecond * 10)
    
    // 计算平均时间
    elapsed := time.Since(start).Milliseconds()
    avgTime.Set(float64(elapsed))
    
    fmt.Fprintln(w, "Hello, World!")
}

func main() {
    // 注册 expvar 处理器
    http.Handle("/debug/vars", expvar.Handler())
    
    // 注册业务处理器
    http.HandleFunc("/", handler)
    
    fmt.Println("Server started on :8080")
    fmt.Println("Metrics: http://localhost:8080/debug/vars")
    http.ListenAndServe(":8080", nil)
}

slog 结构化日志

slog 是 Go 1.21+ 引入的结构化日志库,提供了结构化的日志记录功能,比传统的 log 包更强大和灵活。

基本使用

package main

import (
    "log/slog"
    "os"
)

func main() {
    // 创建默认 logger
    logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
    
    // 记录不同级别的日志
    logger.Debug("Debug message")
    logger.Info("Info message")
    logger.Warn("Warning message")
    logger.Error("Error message")
}

结构化字段

package main

import (
    "log/slog"
    "os"
)

func main() {
    logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
    
    // 添加结构化字段
    logger.Info("User logged in",
        slog.String("user_id", "123"),
        slog.String("username", "alice"),
        slog.String("ip", "192.168.1.1"),
    )
    
    logger.Error("Request failed",
        slog.String("path", "/api/users"),
        slog.Int("status", 500),
        slog.Duration("duration_ms", 150),
    )
}

自定义 Handler

package main

import (
    "context"
    "encoding/json"
    "log/slog"
    "os"
)

// 自定义 Handler
type CustomHandler struct {
    slog.Handler
}

func (h *CustomHandler) Handle(ctx context.Context, r slog.Record) error {
    // 添加自定义字段
    r.AddAttrs(slog.String("service", "myapp"))
    return h.Handler.Handle(ctx, r)
}

func main() {
    handler := &CustomHandler{
        Handler: slog.NewJSONHandler(os.Stdout, nil),
    }
    
    logger := slog.New(handler)
    logger.Info("Test message")
}

日志级别控制

package main

import (
    "log/slog"
    "os"
)

func main() {
    // 设置日志级别
    opts := &slog.HandlerOptions{
        Level: slog.LevelInfo,
    }
    
    logger := slog.New(slog.NewJSONHandler(os.Stdout, opts))
    
    // Debug 级别的日志不会输出
    logger.Debug("Debug message")
    logger.Info("Info message")
}

上下文支持

package main

import (
    "context"
    "log/slog"
    "os"
)

type contextKey struct{}

func main() {
    logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
    
    // 在上下文中添加值
    ctx := context.WithValue(context.Background(), contextKey{}, "request-123")
    
    // 使用上下文记录日志
    logger.InfoContext(ctx, "Processing request")
}

分组日志

package main

import (
    "log/slog"
    "os"
)

func main() {
    logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
    
    // 使用分组
    logger.Info("User action",
        slog.Group("user",
            slog.String("id", "123"),
            slog.String("name", "alice"),
        ),
        slog.Group("request",
            slog.String("path", "/api/users"),
            slog.String("method", "GET"),
        ),
    )
}

与 Gin 集成

package main

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

var logger = slog.New(slog.NewJSONHandler(os.Stdout, nil))

func main() {
    r := gin.Default()
    
    // 自定义中间件
    r.Use(func(c *gin.Context) {
        start := time.Now()
        path := c.Request.URL.Path
        
        c.Next()
        
        logger.Info("Request",
            slog.String("method", c.Request.Method),
            slog.String("path", path),
            slog.Int("status", c.Writer().Status()),
            slog.Duration("duration", time.Since(start)),
        )
    })
    
    r.GET("/", func(c *gin.Context) {
        c.String(200, "Hello, World!")
    })
    
    r.Run(":8080")
}

exp 最佳实践

1. expvar 使用建议

  • 监控关键指标:监控请求计数、错误计数、连接数等关键指标
  • 原子操作:使用 expvar.Int 和 expvar.Float 确保线程安全
  • 合理命名:使用有意义的变量名,便于理解
  • 定期清理:避免积累过多的监控数据
  • 安全考虑:在生产环境中限制 /debug/vars 的访问权限

2. slog 使用建议

  • 结构化字段:使用结构化字段而不是字符串拼接
  • 日志级别:合理使用不同级别的日志
  • 上下文传递:使用上下文传递请求相关信息
  • 性能考虑:避免在高频路径中记录过多日志
  • 日志轮转:配合日志轮转工具管理日志文件

3. 集成建议

// 在应用启动时初始化
func InitMonitoring() {
    // 注册 expvar
    expvar.Publish("version", expvar.String(Version))
    expvar.Publish("build_time", expvar.String(BuildTime))
    
    // 初始化 logger
    opts := &slog.HandlerOptions{
        Level: slog.LevelInfo,
    }
    logger = slog.New(slog.NewJSONHandler(os.Stdout, opts))
}

性能优化建议

  • regexp:预编译正则表达式,避免重复编译
  • sync:根据场景选择合适的锁类型,避免锁竞争
  • json:使用流式处理大文件,避免内存溢出
  • sync.Pool:重用大对象,减少 GC 压力
  • atomic:对简单类型使用原子操作,避免锁开销
  • expvar:使用原子操作更新指标,避免锁竞争
  • slog:在生产环境中使用 JSON 格式,便于日志分析