Go Web 编程实战Go Web 编程实战
首页
课程导读
首页
课程导读
  • 课程导读
  • 课程目录

    • Go基础语法精要
    • Web基础与HTTP处理
    • Gin框架入门
    • 路由与中间件
    • 数据库操作
    • 模板渲染
    • 错误处理与日志
    • 测试与部署
    • 高级中间件模式
    • 微服务架构
    • 性能优化
    • 安全最佳实践
    • 项目结构与代码组织

性能优化

1. Go性能分析工具

CPU分析

import "runtime/pprof"

func main() {
    f, err := os.Create("cpu.prof")
    if err != nil {
        log.Fatal(err)
    }
    defer f.Close()
    
    if err := pprof.StartCPUProfile(f); err != nil {
        log.Fatal(err)
    }
    defer pprof.StopCPUProfile()
    
    // 你的应用代码
}

内存分析

import "runtime/pprof"

func main() {
    f, err := os.Create("mem.prof")
    if err != nil {
        log.Fatal(err)
    }
    defer f.Close()
    
    // 你的应用代码
    
    if err := pprof.WriteHeapProfile(f); err != nil {
        log.Fatal(err)
    }
}

使用pprof工具

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

# 分析内存
go tool pprof mem.prof

# 实时Web分析(适用于HTTP服务)
go tool pprof -http=:8080 http://localhost:6060/debug/pprof/profile

2. CPU和内存优化

减少内存分配

// 不好的做法:频繁分配
func process(data []byte) string {
    return string(data) // 每次分配新字符串
}

// 优化做法:复用缓冲区
var bufPool = sync.Pool{
    New: func() interface{} {
        return bytes.NewBuffer(make([]byte, 0, 1024))
    },
}

func processOptimized(data []byte) string {
    buf := bufPool.Get().(*bytes.Buffer)
    defer bufPool.Put(buf)
    buf.Reset()
    buf.Write(data)
    return buf.String()
}

使用值类型而非指针

// 指针类型(可能增加GC压力)
type User struct {
    Name *string
    Age  *int
}

// 值类型(更高效)
type User struct {
    Name string
    Age  int
}

3. 并发模式优化

工作池模式

func workerPool(jobs <-chan Job, results chan<- Result) {
    var wg sync.WaitGroup
    for i := 0; i < runtime.NumCPU(); i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            for job := range jobs {
                results <- process(job)
            }
        }()
    }
    wg.Wait()
    close(results)
}

批量处理

func batchProcess(items []Item) {
    batchSize := 100
    var wg sync.WaitGroup
    
    for i := 0; i < len(items); i += batchSize {
        wg.Add(1)
        go func(start int) {
            defer wg.Done()
            end := start + batchSize
            if end > len(items) {
                end = len(items)
            }
            processBatch(items[start:end])
        }(i)
    }
    
    wg.Wait()
}

4. HTTP服务优化

连接池配置

func createHTTPClient() *http.Client {
    return &http.Client{
        Transport: &http.Transport{
            MaxIdleConns:        100,
            MaxIdleConnsPerHost: 100,
            IdleConnTimeout:     90 * time.Second,
            TLSHandshakeTimeout: 10 * time.Second,
            DialContext: (&net.Dialer{
                Timeout:   30 * time.Second,
                KeepAlive: 30 * time.Second,
            }).DialContext,
        },
        Timeout: 60 * time.Second,
    }
}

Gin性能优化

func main() {
    // 生产模式(禁用调试和彩色日志)
    gin.SetMode(gin.ReleaseMode)
    
    r := gin.New()
    
    // 使用中间件
    r.Use(gin.Recovery())
    
    // 禁用控制台颜色
    gin.DisableConsoleColor()
    
    // 路由分组
    api := r.Group("/api")
    {
        api.GET("/users", getUsers)
        api.GET("/orders", getOrders)
    }
    
    // 静态文件服务(带缓存控制)
    r.Static("/static", "./public")
    
    // 启动服务
    s := &http.Server{
        Addr:         ":8080",
        Handler:      r,
        ReadTimeout:  30 * time.Second,
        WriteTimeout: 30 * time.Second,
        IdleTimeout:  120 * time.Second,
    }
    s.ListenAndServe()
}

5. 数据库查询优化

批量插入

// 不好的做法:单条插入
for _, user := range users {
    _, err := db.Exec("INSERT INTO users (name, email) VALUES (?, ?)", 
        user.Name, user.Email)
    if err != nil {
        return err
    }
}

// 优化做法:批量插入
valueStrings := make([]string, 0, len(users))
valueArgs := make([]interface{}, 0, len(users)*2)
for _, user := range users {
    valueStrings = append(valueStrings, "(?, ?)")
    valueArgs = append(valueArgs, user.Name)
    valueArgs = append(valueArgs, user.Email)
}
stmt := fmt.Sprintf("INSERT INTO users (name, email) VALUES %s",
    strings.Join(valueStrings, ","))
_, err := db.Exec(stmt, valueArgs...)

使用预处理语句

// 创建预处理语句
stmt, err := db.Prepare("SELECT id, name FROM users WHERE email = ?")
if err != nil {
    log.Fatal(err)
}
defer stmt.Close()

// 复用预处理语句
for _, email := range emails {
    var user User
    err := stmt.QueryRow(email).Scan(&user.ID, &user.Name)
    if err != nil {
        log.Println(err)
        continue
    }
    // 处理用户...
}

索引优化

-- 添加索引
CREATE INDEX idx_users_email ON users(email);

-- 复合索引
CREATE INDEX idx_orders_user_status ON orders(user_id, status);

-- 使用EXPLAIN分析查询
EXPLAIN SELECT * FROM users WHERE email = 'user@example.com';

提示:性能优化应该基于实际测量,而不是猜测。始终使用分析工具识别真正的瓶颈,然后有针对性地优化。

Prev
微服务架构
Next
安全最佳实践