redis/go-redis
GitHub: redis/go-redis
Go 语言编写的 Redis 客户端,用于与 Redis 服务器进行交互。
Stars: 22144 | Forks: 2557
# Go 语言 Redis 客户端
[](https://github.com/redis/go-redis/actions)
[](https://pkg.go.dev/github.com/redis/go-redis/v9?tab=doc)
[](https://redis.io/docs/latest/develop/clients/go/)
[](https://goreportcard.com/report/github.com/redis/go-redis/v9)
[](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工具, 代码覆盖率, 内存数据库, 客户端, 开源框架, 性能监控, 持续集成, 搜索引擎查询, 数据库, 文档, 日志审计, 测试, 版本兼容, 编程语言, 网络编程