redis/go-redis

GitHub: redis/go-redis

Go 语言编写的 Redis 客户端,用于与 Redis 服务器进行交互。

Stars: 22144 | Forks: 2557

# Go 语言 Redis 客户端 [![构建工作流程](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/9ed1eac012082226.svg)](https://github.com/redis/go-redis/actions) [![PkgGoDev](https://pkg.go.dev/badge/github.com/redis/go-redis/v9)](https://pkg.go.dev/github.com/redis/go-redis/v9?tab=doc) [![文档](https://img.shields.io/badge/redis-documentation-informational)](https://redis.io/docs/latest/develop/clients/go/) [![Go Report Card](https://goreportcard.com/badge/github.com/redis/go-redis/v9)](https://goreportcard.com/report/github.com/redis/go-redis/v9) [![codecov](https://codecov.io/github/redis/go-redis/graph/badge.svg?token=tsrCZKuSSw)](https://codecov.io/github/redis/go-redis) ## 支持的版本 在 `go-redis` 中,我们旨在支持 Redis 的最后三个版本。目前,这意味着我们支持: - [Redis 8.0](https://raw.githubusercontent.com/redis/redis/8.0/00-RELEASENOTES) - 使用 Redis CE 8.0 - [Redis 8.2](https://raw.githubusercontent.com/redis/redis/8.2/00-RELEASENOTES) - 使用 Redis CE 8.2 - [Redis 8.4](https://raw.githubusercontent.com/redis/redis/8.4/00-RELEASENOTES) - 使用 Redis CE 8.4 - [Redis 8.8](https://raw.githubusercontent.com/redis/redis/8.8/00-RELEASENOTES) - 使用 Redis CE 8.8 尽管 `go.mod` 中声明它至少需要 `go 1.24`,但我们的 CI 配置为针对所有支持的 Redis 版本和多个 Go 版本([1.24](https://go.dev/doc/devel/release#go1.24.0)、oldstable 和 stable)运行测试。我们观察到,与 Redis Stack 7.2 相关的一些模块测试可能无法通过,并且一些命令在 Redis CE 8.0 中已更改。 尽管它不是官方支持,但 `go-redis/v9` 应该能够与任何 Redis 7.0+ 版本一起工作。如果遇到任何问题,请参阅文档和测试。 ### 数组数据类型(Redis 8.8+) 从 Redis 8.8 开始,go-redis 通过 `AR*` 命令族(`ARSET`、`ARGET`、`ARGETRANGE`、`ARMSET`、`ARMGET`、`ARINSERT`、`ARDEL`、`ARDELRANGE`、`ARLEN`、`ARCOUNT`、`ARNEXT`、`ARSEEK`、`ARSCAN`、`ARGREP`、`ARRING`、`ARLASTITEMS`、`ARINFO`/`ARINFOFULL` 和 `AROP*` 算子)公开了新的数组数据类型。请参阅 `array_commands.go` 以获取完整表面。API 是实验性的,可能在未来的版本中更改。 ## 如何使用 Redis? [在 Redis 工作](https://redis.com/company/careers/jobs/) ## 旧文档 ## 类型化错误 ``` // Cluster and replication errors redis.IsLoadingError(err) // Redis is loading the dataset redis.IsReadOnlyError(err) // Write to read-only replica redis.IsClusterDownError(err) // Cluster is down redis.IsTryAgainError(err) // Command should be retried redis.IsMasterDownError(err) // Master is down redis.IsMovedError(err) // Returns (address, true) if key moved redis.IsAskError(err) // Returns (address, true) if key being migrated // Connection and resource errors redis.IsMaxClientsError(err) // Maximum clients reached redis.IsAuthError(err) // Authentication failed (NOAUTH, WRONGPASS, unauthenticated) redis.IsPermissionError(err) // Permission denied (NOPERM) redis.IsOOMError(err) // Out of memory (OOM) // Transaction errors redis.IsExecAbortError(err) // Transaction aborted (EXECABORT) ``` ### 在钩子中包装错误 在钩子中包装错误时,使用具有 `Unwrap()` 方法(首选)或 `fmt.Errorf` 与 `%w` 的自定义错误类型。始终调用 `cmd.SetErr()` 以保留错误类型信息: ``` // Custom error type (preferred) type AppError struct { Code string RequestID string Err error } func (e *AppError) Error() string { return fmt.Sprintf("[%s] request_id=%s: %v", e.Code, e.RequestID, e.Err) } func (e *AppError) Unwrap() error { return e.Err } // Hook implementation func (h MyHook) ProcessHook(next redis.ProcessHook) redis.ProcessHook { return func(ctx context.Context, cmd redis.Cmder) error { err := next(ctx, cmd) if err != nil { // Wrap with custom error type wrappedErr := &AppError{ Code: "REDIS_ERROR", RequestID: getRequestID(ctx), Err: err, } cmd.SetErr(wrappedErr) return wrappedErr // Return wrapped error to preserve it } return nil } } // Typed error detection works through wrappers if redis.IsLoadingError(err) { // Retry logic } // Extract custom error if needed var appErr *AppError if errors.As(err, &appErr) { log.Printf("Request: %s", appErr.RequestID) } ``` 或者,使用 `fmt.Errorf` 与 `%w`: ``` wrappedErr := fmt.Errorf("context: %w", err) cmd.SetErr(wrappedErr) ``` ### 管道钩子示例 对于管道操作,使用 `ProcessPipelineHook`: ``` type PipelineLoggingHook struct{} func (h PipelineLoggingHook) DialHook(next redis.DialHook) redis.DialHook { return next } func (h PipelineLoggingHook) ProcessHook(next redis.ProcessHook) redis.ProcessHook { return next } func (h PipelineLoggingHook) ProcessPipelineHook(next redis.ProcessPipelineHook) redis.ProcessPipelineHook { return func(ctx context.Context, cmds []redis.Cmder) error { start := time.Now() // Execute the pipeline err := next(ctx, cmds) duration := time.Since(start) log.Printf("Pipeline executed %d commands in %v", len(cmds), duration) // Process individual command errors // Note: Individual command errors are already set on each cmd by the pipeline execution for _, cmd := range cmds { if cmdErr := cmd.Err(); cmdErr != nil { // Check for specific error types using typed error functions if redis.IsAuthError(cmdErr) { log.Printf("Auth error in pipeline command %s: %v", cmd.Name(), cmdErr) } else if redis.IsPermissionError(cmdErr) { log.Printf("Permission error in pipeline command %s: %v", cmd.Name(), cmdErr) } // Optionally wrap individual command errors to add context // The wrapped error preserves type information through errors.As() wrappedErr := fmt.Errorf("pipeline cmd %s failed: %w", cmd.Name(), cmdErr) cmd.SetErr(wrappedErr) } } // Return the pipeline-level error (connection errors, etc.) // You can wrap it if needed, or return it as-is return err } } // Register the hook rdb.AddHook(PipelineLoggingHook{}) // Use pipeline - errors are still properly typed pipe := rdb.Pipeline() pipe.Set(ctx, "key1", "value1", 0) pipe.Get(ctx, "key2") _, err := pipe.Exec(ctx) ``` ## 运行测试 建议使用 Docker,只需运行: ``` make test ``` ## 相关内容 - [Golang ORM](https://bun.uptrace.dev) 用于 PostgreSQL、MySQL、MSSQL 和 SQLite - [Golang PostgreSQL](https://bun.uptrace.dev/postgres/) - [Golang HTTP 路由器](https://bunrouter.uptrace.dev/) - [Golang ClickHouse ORM](https://github.com/uptrace/go-clickhouse) ## 贡献者 感谢所有已经做出贡献的人!
标签:EVTX分析, Go, Go SDK, Go 语言库, Redis, Redis 7.0+, Redis 8.0, Redis 8.2, Redis 8.4, Redis 8.8, Ruby工具, 代码覆盖率, 内存数据库, 客户端, 开源框架, 性能监控, 持续集成, 搜索引擎查询, 数据库, 文档, 日志审计, 测试, 版本兼容, 编程语言, 网络编程