在 Go 中使用 Redis 做计数最常用的库是github.com/redis/go-redis/v9。以下是核心用法和常见场景1. 基础计数操作gopackage main import ( context fmt github.com/redis/go-redis/v9 ) func main() { ctx : context.Background() rdb : redis.NewClient(redis.Options{ Addr: localhost:6379, }) key : page:view:home // INCR - 自增 1 val, err : rdb.Incr(ctx, key).Result() fmt.Println(INCR:, val, err) // INCRBY - 自增指定数值 val, err rdb.IncrBy(ctx, key, 10).Result() fmt.Println(INCRBY:, val, err) // DECR - 自减 1 val, err rdb.Decr(ctx, key).Result() fmt.Println(DECR:, val, err) // DECRBY - 自减指定数值 val, err rdb.DecrBy(ctx, key, 5).Result() fmt.Println(DECRBY:, val, err) }2. 带过期时间的计数如每日统计go// 每日点赞数凌晨自动过期 func incrDailyLike(ctx context.Context, rdb *redis.Client, itemID string) (int64, error) { key : fmt.Sprintf(like:daily:%s:%s, time.Now().Format(2006-01-02), itemID) // 使用 Pipeline 原子执行 INCR EXPIRE pipe : rdb.Pipeline() incr : pipe.Incr(ctx, key) pipe.Expire(ctx, key, 25*time.Hour) // 留点余量 _, err : pipe.Exec(ctx) return incr.Val(), err }3. 限流计数滑动窗口go// 固定窗口限流每分钟内最多 100 次 func rateLimit(ctx context.Context, rdb *redis.Client, userID string) (bool, error) { key : fmt.Sprintf(ratelimit:%s:%d, userID, time.Now().Unix()/60) current, err : rdb.Incr(ctx, key).Result() if err ! nil { return false, err } if current 1 { // 第一次访问设置过期时间 rdb.Expire(ctx, key, time.Minute) } return current 100, nil }4. Hash 字段计数多维度统计go// 统计文章的多维度数据 rdb.HIncrBy(ctx, post:stats:123, views, 1) rdb.HIncrBy(ctx, post:stats:123, likes, 1) rdb.HIncrBy(ctx, post:stats:123, comments, 1) // 获取全部 stats, _ : rdb.HGetAll(ctx, post:stats:123).Result()5. 批量计数Pipelinegopipe : rdb.Pipeline() for i : 0; i 1000; i { pipe.Incr(ctx, fmt.Sprintf(counter:%d, i)) } _, err : pipe.Exec(ctx)关键注意点表格问题方案并发安全Redis 单线程INCR 天然原子无需加锁首次计数key 不存在时 INCR 自动从 0 开始返回 1溢出Redis 整数上限为 64 位有符号整数2^63-1持久化若数据极重要建议开启 AOF 或定期落库如果你有具体场景比如高并发计数、去重计数、分布式 ID 生成可以告诉我我给出更针对性的方案。在 Go 中使用go-redis获取计数值主要用GET系列命令。以下是常见场景的完整示例1. 基础获取gopackage main import ( context fmt strconv github.com/redis/go-redis/v9 ) func main() { ctx : context.Background() rdb : redis.NewClient(redis.Options{Addr: localhost:6379}) // 获取单个计数 val, err : rdb.Get(ctx, page:view:home).Result() if err redis.Nil { fmt.Println(key 不存在计数为 0) } else if err ! nil { panic(err) } else { count, _ : strconv.ParseInt(val, 10, 64) fmt.Println(当前计数:, count) } // 直接获取 int64推荐 count, err : rdb.Get(ctx, page:view:home).Int64() if err redis.Nil { count 0 } fmt.Println(计数:, count) }2. 批量获取多个计数go// MGET 一次性获取多个 key keys : []string{counter:a, counter:b, counter:c} vals, err : rdb.MGet(ctx, keys...).Result() // vals 是 []interface{}不存在的 key 对应 nil for i, v : range vals { if v nil { fmt.Printf(%s 0 (不存在)\n, keys[i]) } else { fmt.Printf(%s %v\n, keys[i], v) } }3. Hash 结构中的计数获取go// HGET 获取单个字段 views, _ : rdb.HGet(ctx, post:stats:123, views).Int64() // HMGET 获取多个字段 fields : []string{views, likes, comments} vals, _ : rdb.HMGet(ctx, post:stats:123, fields...).Result() // HGETALL 获取全部字段 all, _ : rdb.HGetAll(ctx, post:stats:123).Result() fmt.Println(all[views], all[likes])4. 获取并设置过期时间原子操作go// 获取计数同时刷新过期时间如会话活跃统计 pipe : rdb.Pipeline() get : pipe.Get(ctx, session:active:1001) pipe.Expire(ctx, session:active:1001, 30*time.Minute) _, err : pipe.Exec(ctx) count, _ : get.Int64()5. 获取时的类型转换方法go-redis的StringCmd提供了便捷转换表格方法说明.Result()返回(string, error).Int64()直接转int64key 不存在返回redis.Nil错误.Uint64()转uint64.Float64()转float64用于浮点计数.Bool()转bool6. 完整工具函数示例go// GetCounter 安全获取计数key 不存在返回 0 func GetCounter(ctx context.Context, rdb *redis.Client, key string) int64 { n, err : rdb.Get(ctx, key).Int64() if err redis.Nil { return 0 } if err ! nil { // 可打日志或上报 return 0 } return n } // GetCounters 批量获取返回 map[key]count func GetCounters(ctx context.Context, rdb *redis.Client, keys ...string) map[string]int64 { result : make(map[string]int64, len(keys)) if len(keys) 0 { return result } vals, err : rdb.MGet(ctx, keys...).Result() if err ! nil { return result } for i, v : range vals { if v ! nil { if n, ok : v.(string); ok { result[keys[i]], _ strconv.ParseInt(n, 10, 64) } } else { result[keys[i]] 0 } } return result }核心注意点Redis 中INCR等命令存储的是字符串Get返回的是字符串需用.Int64()转换key 不存在时Get返回redis.Nil错误不是返回0。
go redis 计数
在 Go 中使用 Redis 做计数最常用的库是github.com/redis/go-redis/v9。以下是核心用法和常见场景1. 基础计数操作gopackage main import ( context fmt github.com/redis/go-redis/v9 ) func main() { ctx : context.Background() rdb : redis.NewClient(redis.Options{ Addr: localhost:6379, }) key : page:view:home // INCR - 自增 1 val, err : rdb.Incr(ctx, key).Result() fmt.Println(INCR:, val, err) // INCRBY - 自增指定数值 val, err rdb.IncrBy(ctx, key, 10).Result() fmt.Println(INCRBY:, val, err) // DECR - 自减 1 val, err rdb.Decr(ctx, key).Result() fmt.Println(DECR:, val, err) // DECRBY - 自减指定数值 val, err rdb.DecrBy(ctx, key, 5).Result() fmt.Println(DECRBY:, val, err) }2. 带过期时间的计数如每日统计go// 每日点赞数凌晨自动过期 func incrDailyLike(ctx context.Context, rdb *redis.Client, itemID string) (int64, error) { key : fmt.Sprintf(like:daily:%s:%s, time.Now().Format(2006-01-02), itemID) // 使用 Pipeline 原子执行 INCR EXPIRE pipe : rdb.Pipeline() incr : pipe.Incr(ctx, key) pipe.Expire(ctx, key, 25*time.Hour) // 留点余量 _, err : pipe.Exec(ctx) return incr.Val(), err }3. 限流计数滑动窗口go// 固定窗口限流每分钟内最多 100 次 func rateLimit(ctx context.Context, rdb *redis.Client, userID string) (bool, error) { key : fmt.Sprintf(ratelimit:%s:%d, userID, time.Now().Unix()/60) current, err : rdb.Incr(ctx, key).Result() if err ! nil { return false, err } if current 1 { // 第一次访问设置过期时间 rdb.Expire(ctx, key, time.Minute) } return current 100, nil }4. Hash 字段计数多维度统计go// 统计文章的多维度数据 rdb.HIncrBy(ctx, post:stats:123, views, 1) rdb.HIncrBy(ctx, post:stats:123, likes, 1) rdb.HIncrBy(ctx, post:stats:123, comments, 1) // 获取全部 stats, _ : rdb.HGetAll(ctx, post:stats:123).Result()5. 批量计数Pipelinegopipe : rdb.Pipeline() for i : 0; i 1000; i { pipe.Incr(ctx, fmt.Sprintf(counter:%d, i)) } _, err : pipe.Exec(ctx)关键注意点表格问题方案并发安全Redis 单线程INCR 天然原子无需加锁首次计数key 不存在时 INCR 自动从 0 开始返回 1溢出Redis 整数上限为 64 位有符号整数2^63-1持久化若数据极重要建议开启 AOF 或定期落库如果你有具体场景比如高并发计数、去重计数、分布式 ID 生成可以告诉我我给出更针对性的方案。在 Go 中使用go-redis获取计数值主要用GET系列命令。以下是常见场景的完整示例1. 基础获取gopackage main import ( context fmt strconv github.com/redis/go-redis/v9 ) func main() { ctx : context.Background() rdb : redis.NewClient(redis.Options{Addr: localhost:6379}) // 获取单个计数 val, err : rdb.Get(ctx, page:view:home).Result() if err redis.Nil { fmt.Println(key 不存在计数为 0) } else if err ! nil { panic(err) } else { count, _ : strconv.ParseInt(val, 10, 64) fmt.Println(当前计数:, count) } // 直接获取 int64推荐 count, err : rdb.Get(ctx, page:view:home).Int64() if err redis.Nil { count 0 } fmt.Println(计数:, count) }2. 批量获取多个计数go// MGET 一次性获取多个 key keys : []string{counter:a, counter:b, counter:c} vals, err : rdb.MGet(ctx, keys...).Result() // vals 是 []interface{}不存在的 key 对应 nil for i, v : range vals { if v nil { fmt.Printf(%s 0 (不存在)\n, keys[i]) } else { fmt.Printf(%s %v\n, keys[i], v) } }3. Hash 结构中的计数获取go// HGET 获取单个字段 views, _ : rdb.HGet(ctx, post:stats:123, views).Int64() // HMGET 获取多个字段 fields : []string{views, likes, comments} vals, _ : rdb.HMGet(ctx, post:stats:123, fields...).Result() // HGETALL 获取全部字段 all, _ : rdb.HGetAll(ctx, post:stats:123).Result() fmt.Println(all[views], all[likes])4. 获取并设置过期时间原子操作go// 获取计数同时刷新过期时间如会话活跃统计 pipe : rdb.Pipeline() get : pipe.Get(ctx, session:active:1001) pipe.Expire(ctx, session:active:1001, 30*time.Minute) _, err : pipe.Exec(ctx) count, _ : get.Int64()5. 获取时的类型转换方法go-redis的StringCmd提供了便捷转换表格方法说明.Result()返回(string, error).Int64()直接转int64key 不存在返回redis.Nil错误.Uint64()转uint64.Float64()转float64用于浮点计数.Bool()转bool6. 完整工具函数示例go// GetCounter 安全获取计数key 不存在返回 0 func GetCounter(ctx context.Context, rdb *redis.Client, key string) int64 { n, err : rdb.Get(ctx, key).Int64() if err redis.Nil { return 0 } if err ! nil { // 可打日志或上报 return 0 } return n } // GetCounters 批量获取返回 map[key]count func GetCounters(ctx context.Context, rdb *redis.Client, keys ...string) map[string]int64 { result : make(map[string]int64, len(keys)) if len(keys) 0 { return result } vals, err : rdb.MGet(ctx, keys...).Result() if err ! nil { return result } for i, v : range vals { if v ! nil { if n, ok : v.(string); ok { result[keys[i]], _ strconv.ParseInt(n, 10, 64) } } else { result[keys[i]] 0 } } return result }核心注意点Redis 中INCR等命令存储的是字符串Get返回的是字符串需用.Int64()转换key 不存在时Get返回redis.Nil错误不是返回0。