Handling Replies

Redis commands return various data types, and the conn.Do() method in Redigo returns these as interface{}. To make working with these replies easier and safer, Redigo provides a suite of helper functions to convert the generic reply into a specific Go type.

All helper functions share a common signature: func(reply interface{}, err error) (T, error). If the input err is not nil, the helper immediately returns it. This allows for convenient chaining:

// The error from c.Do is passed directly into redis.String
s, err := redis.String(c.Do("GET", "mykey"))
if err != nil {
    // This 'err' could be from the c.Do call or from the type conversion.
}

Nil Replies

When a Redis command returns a nil bulk string (e.g., GET on a non-existent key), the helpers return the zero value for their type and the special error redis.ErrNil.

s, err := redis.String(c.Do("GET", "nonexistent_key"))
if err == redis.ErrNil {
    fmt.Println("Key does not exist.")
} else if err != nil {
    // some other error
} else {
    fmt.Println("Key exists:", s)
}

Basic Type Helpers

These helpers convert replies to common scalar Go types.

  • redis.String(reply, err): Converts a bulk or simple string reply to string.
  • redis.Bytes(reply, err): Converts a bulk or simple string reply to []byte.
  • redis.Int(reply, err): Converts an integer or bulk string reply to int.
  • redis.Int64(reply, err): Converts an integer or bulk string reply to int64.
  • redis.Uint64(reply, err): Converts an integer or bulk string reply to uint64.
  • redis.Float64(reply, err): Converts a bulk string reply to float64.
  • redis.Bool(reply, err): Converts an integer reply to bool (0 is false, others are true).

Array & Slice Helpers

These helpers are used for commands that return arrays, such as LRANGE, SMEMBERS, or MGET.

  • redis.Values(reply, err): Converts an array reply to []interface{}. This is the most generic array helper.
  • redis.Strings(reply, err): Converts an array of bulk strings to []string.
  • redis.ByteSlices(reply, err): Converts an array of bulk strings to [][]byte.
  • redis.Ints(reply, err): Converts an array of integers/bulk strings to []int.
// Example using LRANGE
values, err := redis.Strings(c.Do("LRANGE", "mylist", 0, -1))
if err != nil {
    // handle error
}
for _, v := range values {
    fmt.Println(v)
}

Map Helpers

These helpers are perfect for commands like HGETALL that return an array of alternating keys and values.

  • redis.StringMap(reply, err): Converts an array reply to map[string]string.
  • redis.IntMap(reply, err): Converts to map[string]int.
  • redis.Int64Map(reply, err): Converts to map[string]int64.
// Example using HGETALL
attributes, err := redis.StringMap(c.Do("HGETALL", "user:100"))
if err != nil {
    // handle error
}
fmt.Println("Name:", attributes["name"])

Scanning Helpers

Redigo provides powerful scanning functions to map array replies directly into Go variables or structs.

Scan

Scan copies elements from an array reply into the variables pointed to by dest.

var val1 int
var val2 string
reply, err := redis.Values(c.Do("MGET", "key1", "key2"))
if err != nil {
    // handle error
}

if _, err := redis.Scan(reply, &val1, &val2); err != nil {
    // handle error
}
// val1 and val2 are now populated.

ScanStruct

ScanStruct maps the alternating key-value pairs from a reply (like HGETALL) into the fields of a struct. Field names are matched by default, but can be customized with a redis:"..." tag.

type User struct {
    Name string `redis:"name"`
    Age  int    `redis:"age"`
}

var u User
reply, err := redis.Values(c.Do("HGETALL", "user:100"))
if err != nil {
    // handle error
}

if err := redis.ScanStruct(reply, &u); err != nil {
    // handle error
}

fmt.Printf("%+v\n", u) // {Name:John Doe Age:30}