Executing Commands

Redigo provides a flexible set of methods for executing Redis commands, supporting simple request-reply, pipelining, and transactions.

The Do Method

The most common way to execute a command is with the Do method. It sends a command to the server and returns the received reply.

reply, err := conn.Do("SET", "my_key", "my_value")
// handle err

value, err := conn.Do("GET", "my_key")
// handle err and process value

The Do method accepts the command name as the first argument, followed by a variable number of arguments for the command itself. Redigo automatically converts Go types to Redis bulk strings:

Go Type Conversion
[]byte Sent as is
string Sent as is
int, int64 Converted to a string using strconv
float64 Converted to a string using strconv
bool true becomes "1", false becomes "0"
nil Sent as an empty string ""
Other Types Converted to string using fmt.Fprint

Pipelining

Pipelining is a technique to send multiple commands to the server without waiting for the reply to each one, thereby reducing network latency. Redigo supports pipelining with the Send, Flush, and Receive methods.

  • Send(command, args...): Writes the command to the connection's output buffer.
  • Flush(): Flushes the output buffer to the server, sending all buffered commands.
  • Receive(): Reads a single reply from the server.
// Send two commands without waiting for replies
conn.Send("SET", "foo", "bar")
conn.Send("GET", "foo")

// Flush the buffer to send the commands
conn.Flush()

// Receive the replies sequentially
// Reply from SET
setReply, err := conn.Receive()
if err != nil {
    // handle error
}

// Reply from GET
getReply, err := redis.String(conn.Receive())
if err != nil {
    // handle error
}

fmt.Printf("SET reply: %v\n", setReply)   // e.g., "OK"
fmt.Printf("GET reply: %s\n", getReply) // "bar"

Transactions

Redis transactions (MULTI/EXEC) are a perfect fit for pipelining. You can queue commands within a transaction block and execute them atomically.

// Start the transaction
conn.Send("MULTI")

// Queue commands
conn.Send("INCR", "counter1")
conn.Send("INCR", "counter2")

// Execute the transaction by calling Do("EXEC").
// Do sends EXEC, flushes the buffer, and reads all replies.
replies, err := redis.Values(conn.Do("EXEC"))
if err != nil {
    // handle error
}

// The reply from EXEC is an array of replies for each command in the transaction.
for _, reply := range replies {
    fmt.Println(reply) // Prints the incremented value of counter1, then counter2
}

Redigo also supports optimistic locking using WATCH, UNWATCH, and DISCARD.

Note: The Do method internally flushes the command buffer and then receives all pending replies. It returns the reply for the last command it processed (or an error if any reply was an error). This behavior makes it ideal for executing an EXEC command at the end of a pipelined transaction.