The official Go client for Redis is go-redis . It provides a type-safe, idiomatic Go API with full support for Redis commands, connection pooling, pub/sub, pipelining, transactions, and Redis modules.
Installation
Install go-redis using Go modules:
go get github.com/redis/go-redis/v9
go-redis v9 requires Go 1.18+ and uses the context package for all operations. If you’re using an older Go version, use go-redis v8.
Quick Start
Import and connect
Create a connection to your Redis server: package main
import (
" context "
" fmt "
" github.com/redis/go-redis/v9 "
)
var ctx = context . Background ()
func main () {
// Create Redis client
rdb := redis . NewClient ( & redis . Options {
Addr : "localhost:6379" ,
Password : "" , // no password set
DB : 0 , // use default DB
})
// Test the connection
pong , err := rdb . Ping ( ctx ). Result ()
if err != nil {
panic ( err )
}
fmt . Println ( "Connected to Redis:" , pong )
}
Perform basic operations
Execute Redis commands with context: // SET and GET operations
err := rdb . Set ( ctx , "user:1:name" , "Alice" , 0 ). Err ()
if err != nil {
panic ( err )
}
name , err := rdb . Get ( ctx , "user:1:name" ). Result ()
if err != nil {
panic ( err )
}
fmt . Println ( "Name:" , name ) // Output: Name: Alice
// Work with numbers
err = rdb . Set ( ctx , "counter" , 0 , 0 ). Err ()
if err != nil {
panic ( err )
}
rdb . Incr ( ctx , "counter" )
rdb . IncrBy ( ctx , "counter" , 5 )
count , err := rdb . Get ( ctx , "counter" ). Int ()
if err != nil {
panic ( err )
}
fmt . Println ( "Counter:" , count ) // Output: Counter: 6
// Expiration
err = rdb . Set ( ctx , "session:abc" , "session_data" , time . Hour ). Err ()
if err != nil {
panic ( err )
}
Handle errors
Implement proper error handling: import (
" context "
" errors "
" fmt "
" time "
" github.com/redis/go-redis/v9 "
)
func main () {
ctx := context . Background ()
rdb := redis . NewClient ( & redis . Options {
Addr : "localhost:6379" ,
DialTimeout : 5 * time . Second ,
ReadTimeout : 3 * time . Second ,
WriteTimeout : 3 * time . Second ,
PoolSize : 10 ,
})
defer rdb . Close ()
// Check if key exists
val , err := rdb . Get ( ctx , "nonexistent" ). Result ()
if err == redis . Nil {
fmt . Println ( "Key does not exist" )
} else if err != nil {
fmt . Println ( "Error:" , err )
} else {
fmt . Println ( "Value:" , val )
}
}
Connection Patterns
Basic Connection with Options
rdb := redis . NewClient ( & redis . Options {
Addr : "localhost:6379" ,
Password : "" ,
DB : 0 ,
PoolSize : 10 ,
MinIdleConns : 5 ,
MaxRetries : 3 ,
DialTimeout : 5 * time . Second ,
ReadTimeout : 3 * time . Second ,
WriteTimeout : 3 * time . Second ,
})
Secure TLS Connection
Connect to Redis with TLS encryption:
import (
" crypto/tls "
" github.com/redis/go-redis/v9 "
)
rdb := redis . NewClient ( & redis . Options {
Addr : "your-redis-host.com:6380" ,
Password : "your-password" ,
TLSConfig : & tls . Config {
MinVersion : tls . VersionTLS12 ,
},
})
Redis Cloud Connection
Connect to Redis Cloud:
rdb := redis . NewClient ( & redis . Options {
Addr : "your-endpoint.redis.cloud:12345" ,
Password : "your-password" ,
TLSConfig : & tls . Config {
MinVersion : tls . VersionTLS12 ,
},
})
Connection Pool Configuration
rdb := redis . NewClient ( & redis . Options {
Addr : "localhost:6379" ,
PoolSize : 100 , // Maximum number of socket connections
MinIdleConns : 10 , // Minimum number of idle connections
MaxIdleTime : 5 * time . Minute , // Close idle connections after this time
PoolTimeout : 4 * time . Second , // Wait time when all connections are busy
})
Working with Data Structures
Hashes
// Store user data as a hash
err := rdb . HSet ( ctx , "user:1" , map [ string ] interface {}{
"name" : "Alice" ,
"email" : "[email protected] " ,
"age" : 30 ,
}). Err ()
if err != nil {
panic ( err )
}
// Get specific field
name , err := rdb . HGet ( ctx , "user:1" , "name" ). Result ()
if err != nil {
panic ( err )
}
// Get all fields
user , err := rdb . HGetAll ( ctx , "user:1" ). Result ()
if err != nil {
panic ( err )
}
fmt . Println ( user ) // map[name:Alice email:[email protected] age:30]
// Increment numeric field
rdb . HIncrBy ( ctx , "user:1" , "age" , 1 )
Lists
// Add items to a list
err := rdb . RPush ( ctx , "queue" , "task1" , "task2" , "task3" ). Err ()
if err != nil {
panic ( err )
}
// Get list length
length , err := rdb . LLen ( ctx , "queue" ). Result ()
// Pop item from list
task , err := rdb . LPop ( ctx , "queue" ). Result ()
fmt . Println ( task ) // task1
// Get range of items
tasks , err := rdb . LRange ( ctx , "queue" , 0 , - 1 ). Result ()
Sets
// Add members to a set
err := rdb . SAdd ( ctx , "tags" , "python" , "redis" , "database" ). Err ()
if err != nil {
panic ( err )
}
// Check membership
isMember , err := rdb . SIsMember ( ctx , "tags" , "python" ). Result ()
fmt . Println ( isMember ) // true
// Get all members
tags , err := rdb . SMembers ( ctx , "tags" ). Result ()
// Set operations
rdb . SAdd ( ctx , "tags2" , "redis" , "cache" , "nosql" )
common , err := rdb . SInter ( ctx , "tags" , "tags2" ). Result ()
fmt . Println ( common ) // [redis]
Sorted Sets
// Add scored members
err := rdb . ZAdd ( ctx , "leaderboard" ,
redis . Z { Score : 100 , Member : "alice" },
redis . Z { Score : 150 , Member : "bob" },
redis . Z { Score : 120 , Member : "charlie" },
). Err ()
if err != nil {
panic ( err )
}
// Get top scores (descending)
topPlayers , err := rdb . ZRevRangeWithScores ( ctx , "leaderboard" , 0 , 2 ). Result ()
for _ , player := range topPlayers {
fmt . Printf ( " %s : %.0f \n " , player . Member , player . Score )
}
// Get rank
rank , err := rdb . ZRevRank ( ctx , "leaderboard" , "alice" ). Result ()
fmt . Println ( rank ) // 2 (0-indexed)
// Increment score
rdb . ZIncrBy ( ctx , "leaderboard" , 25 , "alice" )
Advanced Features
Pipelining
Batch multiple commands for better performance:
pipe := rdb . Pipeline ()
pipe . Set ( ctx , "key1" , "value1" , 0 )
pipe . Set ( ctx , "key2" , "value2" , 0 )
pipe . Incr ( ctx , "counter" )
getCmd := pipe . Get ( ctx , "key1" )
// Execute all commands
_ , err := pipe . Exec ( ctx )
if err != nil {
panic ( err )
}
// Get individual results
fmt . Println ( getCmd . Val ()) // value1
Transactions
Execute commands atomically with WATCH:
// Transaction with optimistic locking
func transferFunds ( ctx context . Context , rdb * redis . Client , fromKey , toKey string , amount int64 ) error {
txf := func ( tx * redis . Tx ) error {
// Get current balance
balance , err := tx . Get ( ctx , fromKey ). Int64 ()
if err != nil && err != redis . Nil {
return err
}
if balance < amount {
return errors . New ( "insufficient balance" )
}
// Execute transaction
_ , err = tx . TxPipelined ( ctx , func ( pipe redis . Pipeliner ) error {
pipe . DecrBy ( ctx , fromKey , amount )
pipe . IncrBy ( ctx , toKey , amount )
return nil
})
return err
}
// Retry if the key was modified
return rdb . Watch ( ctx , txf , fromKey )
}
Pub/Sub
Implement publish/subscribe messaging:
import (
" context "
" fmt "
" github.com/redis/go-redis/v9 "
)
func subscriber ( ctx context . Context ) {
rdb := redis . NewClient ( & redis . Options {
Addr : "localhost:6379" ,
})
// Subscribe to a channel
pubsub := rdb . Subscribe ( ctx , "notifications" )
defer pubsub . Close ()
// Wait for subscription to be confirmed
_ , err := pubsub . Receive ( ctx )
if err != nil {
panic ( err )
}
// Receive messages
ch := pubsub . Channel ()
for msg := range ch {
fmt . Printf ( "Received: %s from %s \n " , msg . Payload , msg . Channel )
}
}
func publisher ( ctx context . Context ) {
rdb := redis . NewClient ( & redis . Options {
Addr : "localhost:6379" ,
})
err := rdb . Publish ( ctx , "notifications" , "Hello, Redis!" ). Err ()
if err != nil {
panic ( err )
}
}
Scan for Large Datasets
Iterate through keys efficiently:
iter := rdb . Scan ( ctx , 0 , "user:*" , 100 ). Iterator ()
for iter . Next ( ctx ) {
key := iter . Val ()
fmt . Println ( key )
// Process each key
value , err := rdb . Get ( ctx , key ). Result ()
if err != nil {
continue
}
fmt . Println ( value )
}
if err := iter . Err (); err != nil {
panic ( err )
}
Context and Timeouts
Use context for timeout control:
import (
" context "
" time "
)
// Set operation timeout
ctx , cancel := context . WithTimeout ( context . Background (), 5 * time . Second )
defer cancel ()
err := rdb . Set ( ctx , "key" , "value" , 0 ). Err ()
if err != nil {
if errors . Is ( err , context . DeadlineExceeded ) {
fmt . Println ( "Operation timed out" )
} else {
fmt . Println ( "Error:" , err )
}
}
Cluster Support
Connect to Redis Cluster:
import " github.com/redis/go-redis/v9 "
rdb := redis . NewClusterClient ( & redis . ClusterOptions {
Addrs : [] string {
"localhost:7000" ,
"localhost:7001" ,
"localhost:7002" ,
},
PoolSize : 10 ,
})
// Use the same API as single-node client
err := rdb . Set ( ctx , "key" , "value" , 0 ). Err ()
Starter Project
Redis Go Starter Project Clone the official starter project to get up and running quickly with complete examples and best practices.
Additional Resources
go-redis Documentation Official go-redis documentation
GitHub Repository go-redis source code and examples
Redis Commands Complete Redis command reference
Data Types Guide Learn about Redis data structures