错误处理
Go Cursor SDK 提供了详细的错误类型和错误处理机制,帮助开发者快速定位和解决问题。
错误类型
常见错误
SDK 定义了以下常见错误类型:
go
var (
ErrStorageNotFound = errors.New("cursor storage not found")
ErrDatabaseOpen = errors.New("failed to open database")
ErrDatabaseQuery = errors.New("database query failed")
ErrInvalidConfig = errors.New("invalid configuration")
ErrReaderNotFound = errors.New("reader not found")
ErrCacheMiss = errors.New("cache miss")
ErrExportFailed = errors.New("export failed")
ErrWatcherNotEnabled = errors.New("watcher not enabled")
)基本错误处理
检查错误
go
client, err := cursor.NewCursorClient(config)
if err != nil {
log.Fatal(err)
}
defer client.Close()
sessions, err := client.Sessions().ListSessions()
if err != nil {
log.Printf("获取会话失败:%v\n", err)
return
}使用 errors.Is
go
sessions, err := client.Sessions().ListSessions()
if err != nil {
if errors.Is(err, cursor.ErrDatabaseQuery) {
log.Println("数据库查询失败")
} else if errors.Is(err, cursor.ErrStorageNotFound) {
log.Println("Cursor 存储路径未找到")
} else {
log.Printf("未知错误:%v\n", err)
}
return
}使用 errors.As
go
var dbErr *cursor.DatabaseError
if errors.As(err, &dbErr) {
log.Printf("数据库错误:%s (代码:%d)\n", dbErr.Message, dbErr.Code)
}错误恢复
重试机制
go
func listSessionsWithRetry(client *cursor.CursorClient, maxRetries int) ([]cursor.Session, error) {
var sessions []cursor.Session
var err error
for i := 0; i < maxRetries; i++ {
sessions, err = client.Sessions().ListSessions()
if err == nil {
return sessions, nil
}
log.Printf("尝试 %d/%d 失败:%v\n", i+1, maxRetries, err)
time.Sleep(time.Second * time.Duration(i+1))
}
return nil, fmt.Errorf("重试 %d 次后仍然失败:%w", maxRetries, err)
}降级处理
go
func getSessionsWithFallback(client *cursor.CursorClient) []cursor.Session {
// 尝试从缓存获取
sessions, err := client.Sessions().ListSessions()
if err == nil {
return sessions
}
log.Printf("获取会话失败,使用空列表:%v\n", err)
return []cursor.Session{}
}错误日志
结构化日志
go
func processSession(client *cursor.CursorClient, sessionID string) error {
session, err := client.Sessions().GetSessionByID(sessionID)
if err != nil {
log.Printf("错误:获取会话失败 | 会话ID=%s | 错误=%v\n",
sessionID, err)
return err
}
// 处理会话...
return nil
}使用日志库
go
import "github.com/sirupsen/logrus"
func processData(client *cursor.CursorClient) error {
sessions, err := client.Sessions().ListSessions()
if err != nil {
logrus.WithFields(logrus.Fields{
"error": err,
"func": "processData",
}).Error("获取会话失败")
return err
}
logrus.WithFields(logrus.Fields{
"count": len(sessions),
}).Info("成功获取会话")
return nil
}错误传播
包装错误
go
func loadUserData(client *cursor.CursorClient) error {
sessions, err := client.Sessions().ListSessions()
if err != nil {
return fmt.Errorf("加载用户数据失败:%w", err)
}
// 处理数据...
return nil
}自定义错误
go
type DataProcessError struct {
Operation string
Err error
}
func (e *DataProcessError) Error() string {
return fmt.Sprintf("数据处理错误 [%s]:%v", e.Operation, e.Err)
}
func (e *DataProcessError) Unwrap() error {
return e.Err
}
func processData(client *cursor.CursorClient) error {
sessions, err := client.Sessions().ListSessions()
if err != nil {
return &DataProcessError{
Operation: "ListSessions",
Err: err,
}
}
// 处理数据...
return nil
}错误监控
错误统计
go
type ErrorStats struct {
mu sync.Mutex
errors map[string]int
}
func (s *ErrorStats) Record(err error) {
s.mu.Lock()
defer s.mu.Unlock()
errType := fmt.Sprintf("%T", err)
s.errors[errType]++
}
func (s *ErrorStats) Report() {
s.mu.Lock()
defer s.mu.Unlock()
log.Println("错误统计:")
for errType, count := range s.errors {
log.Printf(" %s: %d 次\n", errType, count)
}
}错误告警
go
func processWithAlert(client *cursor.CursorClient) error {
sessions, err := client.Sessions().ListSessions()
if err != nil {
// 发送告警
sendAlert("获取会话失败", err)
return err
}
return nil
}
func sendAlert(message string, err error) {
// 发送到告警系统
log.Printf("告警:%s | 错误:%v\n", message, err)
}实际示例
完整的错误处理示例
go
package main
import (
"errors"
"fmt"
"log"
cursor "github.com/vibe-coding-labs/go-cursor-sdk"
)
func main() {
if err := run(); err != nil {
log.Fatal(err)
}
}
func run() error {
// 创建客户端
client, err := cursor.NewCursorClient(nil)
if err != nil {
return handleClientError(err)
}
defer client.Close()
// 获取会话
sessions, err := getSessions(client)
if err != nil {
return fmt.Errorf("获取会话失败:%w", err)
}
// 处理会话
if err := processSessions(sessions); err != nil {
return fmt.Errorf("处理会话失败:%w", err)
}
return nil
}
func handleClientError(err error) error {
switch {
case errors.Is(err, cursor.ErrStorageNotFound):
return fmt.Errorf("Cursor 未安装或存储路径未找到:%w", err)
case errors.Is(err, cursor.ErrDatabaseOpen):
return fmt.Errorf("无法打开数据库,请检查权限:%w", err)
default:
return fmt.Errorf("创建客户端失败:%w", err)
}
}
func getSessions(client *cursor.CursorClient) ([]cursor.Session, error) {
sessions, err := client.Sessions().ListSessions()
if err != nil {
if errors.Is(err, cursor.ErrDatabaseQuery) {
// 尝试从缓存获取
log.Println("数据库查询失败,尝试从缓存获取")
return getSessionsFromCache(client)
}
return nil, err
}
return sessions, nil
}
func getSessionsFromCache(client *cursor.CursorClient) ([]cursor.Session, error) {
// 实现缓存获取逻辑
return nil, errors.New("缓存未实现")
}
func processSessions(sessions []cursor.Session) error {
for _, session := range sessions {
if err := processSession(session); err != nil {
log.Printf("处理会话 %s 失败:%v\n", session.ID, err)
continue // 继续处理其他会话
}
}
return nil
}
func processSession(session cursor.Session) error {
// 处理单个会话
return nil
}最佳实践
- 始终检查错误
- 使用 errors.Is 和 errors.As 判断错误类型
- 包装错误以提供上下文
- 记录详细的错误日志
- 实现重试和降级机制
- 监控和统计错误
- 为用户提供友好的错误信息