Skip to content

Redis ​

Before You Start

  • Applies to: Go 1.21+ (examples verified with Go 1.22) · Prerequisites: Std: strings · Read time: about 12 min

Redis is an open-source key-value storage database written in ANSI C, compliant with the BSD license, supporting network connectivity, in-memory operation, distributed architecture, and optional persistence. It provides APIs for multiple programming languages. Redis can be used as a NoSQL database, a high-speed cache storage, and also supports simple message queuing.

This article only explains how to use the Go language driver to operate the Redis database and does not cover Redis itself.

Official documentation: Golang Redis client (uptrace.dev)

Official repository: go-redis/redis: Type-safe Redis client for Golang (github.com)

Installation ​

There are many drivers available for Redis. This article uses github.com/go-redis/redis.

If your Redis version is 6:

go get github.com/go-redis/redis/v8

If your Redis version is 7:

go get github.com/go-redis/redis/v9

Quick Start ​

go
import (
   "fmt"
   "log"
   "testing"

   "github.com/go-redis/redis"
)

func TestQuickStart(t *testing.T) {
   // Create Redis connection client
   redisClient := redis.NewClient(&redis.Options{
      Addr:     "192.168.48.134:6379",
      Password: "123456",
      DB:       0, // Use default DB
   })

   // Set key-value pair, 0 means never expire
   redisClient.Set("hello", "world", 0)

   // Read value
   result, err := redisClient.Get("hello").Result()
   if err == redis.Nil {
      fmt.Println("key not exist")
   } else if err != nil {
      log.Panic(err)
   }
   fmt.Println(result)
}

Connection Configuration ​

go
type Options struct {
  // Network type: tcp or unix.
  // Default is tcp.
  Network string
  // Redis address, format: host:port
  Addr string

    // Dialer creates a new network connection and has higher priority than
  // Network and Addr options.
  Dialer func() (net.Conn, error)

  // Hook that is called when a new connection is created
  OnConnect func(*Conn) error

  // Redis password, can be empty if redis server has no password set.
  Password string

  // Redis database, starting from 0, default is 0, can be left unset.
  DB int

  // Maximum number of retries for failed Redis operations, default 0.
  MaxRetries int

  // Minimum retry backoff interval.
  // Default is 8ms; -1 disables retries.
  MinRetryBackoff time.Duration

  // Maximum retry backoff interval.
  // Default is 512ms; -1 disables retries.
  MaxRetryBackoff time.Duration

  // Timeout for dialing a new Redis connection.
  // Default is 5 seconds.
  DialTimeout time.Duration

  // Socket read timeout.
  // Default is 3 seconds.
  ReadTimeout time.Duration

  // Socket write timeout.
  WriteTimeout time.Duration

  // Maximum number of connections in the Redis connection pool.
  // Default pool size equals CPU count * 10.
  PoolSize int

  // Minimum number of idle connections in the Redis connection pool.
  MinIdleConns int

  // Maximum lifetime of a connection in the pool; stale connections are not closed by default.
  MaxConnAge time.Duration

  // Maximum time the pool waits for a connection after one has been taken out.
  // Default is ReadTimeout + 1 second.
  PoolTimeout time.Duration

  // How often idle connections are closed.
  // Default is 5 minutes. -1 disables this option.
  IdleTimeout time.Duration

  // How often to check for idle connections.
  // Default is 1 minute. -1 disables idle connection checking.
  IdleCheckFrequency time.Duration

  // Read-only setting. If set to true, Redis can only query cache on the current node instance and cannot update.
  readOnly bool

    // TLS configuration
  TLSConfig *tls.Config
}

Establishing Connection ​

go
// Create Redis connection client
redisClient := redis.NewClient(&redis.Options{
    Addr:     "192.168.48.134:6379",
    Password: "123456",
    DB:       0, // Use default DB
})

Closing Connection ​

The driver maintains an internal connection pool, so you don't need to close the connection after each operation.

go
defer redisClient.Close()

This Redis driver has encapsulated almost all operations. Redis commands and method names correspond one-to-one. Basically, if you know how to use Redis commands, you'll know how to use the driver methods.

Redis commands: redis command manual

Basic Operations ​

Delete Key ​

go
redisClient.Set("name", "jack", 0)
fmt.Println(redisClient.Del("name").Result())

Expiration Time ​

go
redisClient.Set("name", "jack", 0)
// Set expiration time
redisClient.Expire("name", time.Second*2)
fmt.Println(redisClient.Get("name").Val())
time.Sleep(time.Second * 3)
fmt.Println(redisClient.Get("name").Val())

Cancel Expiration Time ​

go
redisClient.Set("name", "jack", 2)
// Cancel expiration time
redisClient.Persist("name")
time.Sleep(time.Second * 2)
fmt.Println(redisClient.Get("name"))

Query Expiration Time ​

go
fmt.Println(redisClient.TTL("name"))
fmt.Println(redisClient.PTTL("name"))

Rename ​

go
redisClient.Rename("name", "newName")

Query Type ​

go
redisClient.Type("name")

Scan ​

go
fmt.Println(redisClient.Scan(0, "", 4))

Strings ​

Simple Set/Get ​

go
redisClient.Set("token", "abcefghijklmn", 0)
fmt.Println(redisClient.Get("token").Val())

Batch Set/Get ​

go
redisClient.MSet("cookie", "12345", "token", "abcefg")
fmt.Println(redisClient.MGet("cookie", "token").Val())

Increment/Decrement Numbers ​

go
redisClient.Set("age", "1", 0)
// Increment
redisClient.Incr("age")
fmt.Println(redisClient.Get("age").Val())
// Decrement
redisClient.Decr("age")
fmt.Println(redisClient.Get("age").Val())

Hashes ​

Read/Write Operations ​

go
// Set single field
redisClient.HSet("map", "name", "jack")
// Set multiple fields
redisClient.HMSet("map", map[string]interface{}{"a": "b", "c": "d", "e": "f"})
// Get single field
fmt.Println(redisClient.HGet("map", "a").Val())
// Get multiple fields
fmt.Println(redisClient.HMGet("map", "a", "b").Val())
// Get entire map
fmt.Println(redisClient.HGetAll("map").Val())

Output:

b
[b <nil>]
map[a:b c:d e:f name:jack]

Delete Key ​

go
// Delete a field from the map
redisClient.HDel("map", "a")

Check if Key Exists ​

go
// Check if field exists
redisClient.HExists("map", "a")

Get All Keys ​

go
// Get all keys of the map
redisClient.HKeys("map")

Get Hash Table Length ​

go
// Get map length
redisClient.HLen("map")

Iterate Hash Key-Value Pairs ​

go
// Iterate key-value pairs in the map
redisClient.HScan("map", 0, "", 1)

Lists ​

Modify Elements ​

go
// Add to left
redisClient.LPush("list", "a", "b", "c", "d", "e")
// Add to right
redisClient.RPush("list", "g", "i", "a")
// Insert value before reference value
redisClient.LInsertBefore("list", "a", "aa")
// Insert value after reference value
redisClient.LInsertAfter("list", "a", "gg")
// Set value of element at specified index
redisClient.LSet("list", 0, "head")

Access Length ​

go
// Access list length
redisClient.LLen("list")

Access Elements ​

go
// Pop element from left
redisClient.LPop("list")
// Pop element from right
redisClient.RPop("list")
// Access element at specified index
redisClient.LIndex("list", 1)
// Access elements in specified range
redisClient.LRange("list", 0, 1)

Delete Elements ​

go
// Delete specified element
redisClient.LRem("list", 0, "a")
// Delete elements in specified range
redisClient.LTrim("list", 0, 1)
// Keep elements in specified range
redisClient.LTrim("list", 0, 1)

Sets ​

Add Elements ​

go
// Add elements to a set
redisClient.SAdd("set", "a", "b", "c")
redisClient.SAdd("set2", "c", "d", "e")

Access Set Elements ​

go
// Get all members of the set
redisClient.SMembers("set")
// Check if an element belongs to the set
redisClient.SIsMember("set", "a")
// Randomly return count elements
redisClient.SRandMemberN("set", 1)
// Get the number of elements in a set
redisClient.SCard("set")

Set Operations ​

go
// Return the difference of given sets
redisClient.SDiff("set", "set2")
// Store the difference of given sets in the result set, return the length of the result set
redisClient.SDiffStore("store", "set", "se2")
// Return the intersection of given sets
redisClient.SInter("set", "set2")
// Store the intersection of given sets in the result set, return the length of the result set
redisClient.SInterStore("store", "set", "set2")
// Return the union of given sets
redisClient.SUnion("set", "set2")
// Store the union of given sets in the result set, return the length of the result set
redisClient.SUnionStore("store", "set", "store")

Delete Elements ​

go
// Pop and delete the element
redisClient.SPop("set")
// Pop and delete N elements
redisClient.SPopN("set", 2)

Move Elements ​

go
// Move specified element from source set to target set
redisClient.SMove("set", "set2", "a")

Delete Elements ​

go
// Delete specified elements
redisClient.SRem("set", "a", "b")

Iterate ​

go
// Iterate over the set
redisClient.SScan("set", 0, "", 2)

Sorted Sets ​

Add Elements ​

go
// Add elements to a sorted set
redisClient.ZAdd("ss", redis.Z{
   Score:  1,
   Member: "a",
}, redis.Z{
   Score:  2,
   Member: "b",
})

Element Ranking ​

go
// Return the rank of the element in the sorted set, sorted from low to high
redisClient.ZRank("ss", "1")
// Return the rank of the element in the sorted set, sorted from high to low
redisClient.ZRevRank("ss", "1")

Access Elements ​

go
// Return the number of members between min and max
redisClient.ZCount("ss", "1", "2")

// Return the score of the element
redisClient.ZScore("ss", "a")

// Return elements in the specified range
redisClient.ZRange("ss", 1, 2)
// Return all members between min and max
redisClient.ZRangeByScore("ss", redis.ZRangeBy{
   Min:    "1",
   Max:    "2",
   Offset: 0,
   Count:  1,
})

Modify Score ​

go
// Increase the score of a specified element
redisClient.ZIncr("ss", redis.Z{
   Score:  2,
   Member: "b",
})

Delete Elements ​

go
// Delete specified element
redisClient.ZRem("ss", "a")
// Delete elements in the specified rank range
redisClient.ZRemRangeByRank("ss", 1, 2)
// Delete elements with scores between min and max
redisClient.ZRemRangeByScore("ss", "1", "2")

Scripts ​

go
// Load script, return sha value
redisClient.ScriptLoad("return 0")
// Execute script by sha value
redisClient.EvalSha("sha", []string{}, "")
// Execute script directly
redisClient.Eval("return 0", []string{}, "")
// Clear script cache
redisClient.ScriptFlush()
// Kill the currently running script
redisClient.ScriptKill()
// Verify if the script for the corresponding hash value exists
redisClient.ScriptExists("")

Pub/Sub ​

go
// Send message to specified channel
redisClient.Publish("channel", "message")
// Subscribe to specified channel
redisClient.Subscribe("channel")
// Check subscription status
redisClient.PubSubNumSub("channel")

Complete Example ​

The program below runs as-is: copy it into a file and execute go run main.go, or paste it into the Go Playground.

go
package main

import (
	"fmt"
	"strings"
)

func main() {
	args := []string{"SET", "user:1", "gopher"}

	// Redis clients speak RESP: *N then N bulk strings
	var sb strings.Builder
	fmt.Fprintf(&sb, "*%d\r\n", len(args))
	for _, a := range args {
		fmt.Fprintf(&sb, "$%d\r\n%s\r\n", len(a), a)
	}

	fmt.Printf("%q\n", sb.String())
}

Expected output:

text
"*3\r\n$3\r\nSET\r\n$6\r\nuser:1\r\n$6\r\ngopher\r\n"

Common Pitfalls ​

  • Clients are concurrency-safe. go-redis can be shared across goroutines; one client per process is the norm.
  • Set TTLs. Keys without expiry accumulate until the instance runs out of memory.
  • Watch out for big keys. A single huge HGETALL or KEYS call blocks the server; scan and split instead.
  • Use pipelines for batches. Round trips dominate latency; a pipeline cuts them without giving up atomicity per command.
  • Pub/Sub is fire-and-forget. Messages are not persisted; use Streams when delivery must survive a restart.

Change Log ​

  • 2026-10-14: Added "Before You Start" notes, a complete runnable example with expected output, common pitfalls, and this change log. Closed a code block that was left unterminated.

Golang by www.golangdev.cn · Adapted in part from Golang 中文学习文档 (MIT, © 寒江蓑笠翁)