资源管理
正确的资源管理对于构建稳定可靠的应用至关重要。本文档介绍 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)
}
}最佳实践总结
- 始终使用 defer 关闭资源
- 使用统一客户端管理 Reader
- 分批处理大量数据
- 及时释放不需要的对象
- 使用 context 控制操作超时
- 定期清理缓存和触发 GC
- 监控资源使用情况
- 正确处理错误和 panic