Skip to content

资源管理

正确的资源管理对于构建稳定可靠的应用至关重要。本文档介绍 Go Cursor SDK 的资源管理最佳实践。

基本原则

始终关闭客户端

go
client, err := cursor.NewCursorClient(config)
if err != nil {
    log.Fatal(err)
}
defer client.Close() // 确保资源被释放

使用 defer 确保清理

go
func processData() error {
    client, err := cursor.NewCursorClient(nil)
    if err != nil {
        return err
    }
    defer client.Close()
    
    // 处理数据...
    
    return nil
}

数据库连接管理

连接池

SDK 内部使用连接池管理数据库连接:

go
config := &cursor.ClientConfig{
    MaxOpenConns: 10,  // 最大打开连接数
    MaxIdleConns: 5,   // 最大空闲连接数
}

client, err := cursor.NewCursorClient(config)

连接超时

go
config := &cursor.ClientConfig{
    ConnTimeout: 30 * time.Second, // 连接超时时间
}

client, err := cursor.NewCursorClient(config)

Reader 生命周期

使用统一客户端(推荐)

go
// 推荐:使用统一客户端管理所有 Reader
client, err := cursor.NewCursorClient(config)
defer client.Close() // 自动关闭所有 Reader

sessions, _ := client.Sessions().ListSessions()
composers, _ := client.Composers().ListComposers()

直接使用 Reader(不推荐)

go
// 不推荐:需要手动管理每个 Reader
sessionReader, err := cursor.NewSessionReader(config)
defer sessionReader.Close()

composerReader, err := cursor.NewComposerReader(config)
defer composerReader.Close()

内存管理

及时释放大对象

go
// 处理大量数据时,及时释放不需要的对象
sessions, err := client.Sessions().ListSessions()
if err != nil {
    log.Fatal(err)
}

// 处理数据
for _, session := range sessions {
    processSession(session)
}

// 释放内存
sessions = nil
runtime.GC() // 建议垃圾回收

分批处理数据

go
// 避免一次性加载所有数据
pageSize := 100
page := 0

for {
    query := cursor.NewQueryBuilder().
        Offset(page * pageSize).
        Limit(pageSize).
        Build()
    
    sessions, err := client.Sessions().QuerySessions(query)
    if err != nil {
        log.Fatal(err)
    }
    
    if len(sessions) == 0 {
        break
    }
    
    // 处理当前批次
    for _, session := range sessions {
        processSession(session)
    }
    
    page++
}

并发资源管理

使用 sync.WaitGroup

go
var wg sync.WaitGroup

// 并发处理多个任务
for i := 0; i < 10; i++ {
    wg.Add(1)
    go func(id int) {
        defer wg.Done()
        
        // 处理任务
        sessions, err := client.Sessions().ListSessions()
        if err != nil {
            log.Printf("任务 %d 失败:%v\n", id, err)
            return
        }
        
        // 处理数据...
    }(i)
}

// 等待所有任务完成
wg.Wait()

使用 context 控制生命周期

go
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

// 使用 context 控制操作
sessions, err := client.Sessions().ListSessionsWithContext(ctx)
if err != nil {
    if errors.Is(err, context.DeadlineExceeded) {
        log.Println("操作超时")
    }
    log.Fatal(err)
}

错误处理与资源清理

确保资源在错误时也被释放

go
func processData() (err error) {
    client, err := cursor.NewCursorClient(nil)
    if err != nil {
        return err
    }
    defer func() {
        if closeErr := client.Close(); closeErr != nil {
            if err == nil {
                err = closeErr
            }
        }
    }()
    
    // 处理数据...
    
    return nil
}

使用 panic 恢复

go
func safeProcess() (err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("panic recovered: %v", r)
        }
    }()
    
    client, err := cursor.NewCursorClient(nil)
    if err != nil {
        return err
    }
    defer client.Close()
    
    // 可能 panic 的操作...
    
    return nil
}

长时间运行的应用

定期清理资源

go
func runDaemon() {
    client, err := cursor.NewCursorClient(config)
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()
    
    // 定期清理缓存
    ticker := time.NewTicker(1 * time.Hour)
    defer ticker.Stop()
    
    for {
        select {
        case <-ticker.C:
            // 清理缓存
            client.Cache().Clear()
            
            // 触发垃圾回收
            runtime.GC()
            
            log.Println("资源清理完成")
        }
    }
}

监控资源使用

go
// 定期输出资源使用情况
func monitorResources(client *cursor.CursorClient) {
    ticker := time.NewTicker(5 * time.Minute)
    defer ticker.Stop()
    
    for range ticker.C {
        var m runtime.MemStats
        runtime.ReadMemStats(&m)
        
        log.Printf("内存使用:%d MB\n", m.Alloc/1024/1024)
        log.Printf("缓存大小:%d\n", client.Cache().Stats().Size)
    }
}

最佳实践总结

  1. 始终使用 defer 关闭资源
  2. 使用统一客户端管理 Reader
  3. 分批处理大量数据
  4. 及时释放不需要的对象
  5. 使用 context 控制操作超时
  6. 定期清理缓存和触发 GC
  7. 监控资源使用情况
  8. 正确处理错误和 panic

下一步

Released under the MIT License.