redis

package
v0.3.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 28, 2013 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Example (Zpop)

This example implements ZPOP as described at http://redis.io/topics/transactions using WATCH/MULTI/EXEC and scripting.

package main

import (
	"fmt"
	"github.com/stephenalexbrowne/zoom/redis"
)

// zpop pops a value from the ZSET key using WATCH/MULTI/EXEC commands.
func zpop(c redis.Conn, key string) (result string, err error) {

	defer func() {
		// Return connection to normal state on error.
		if err != nil {
			c.Do("DISCARD")
		}
	}()

	// Loop until transaction is successful.
	for {
		if _, err := c.Do("WATCH", key); err != nil {
			return "", err
		}

		members, err := redis.Strings(c.Do("ZRANGE", key, 0, 0))
		if err != nil {
			return "", err
		}
		if len(members) != 1 {
			return "", redis.ErrNil
		}

		c.Send("MULTI")
		c.Send("ZREM", key, members[0])
		queued, err := c.Do("EXEC")
		if err != nil {
			return "", err
		}

		if queued != nil {
			result = members[0]
			break
		}
	}

	return result, nil
}

// zpopScript pops a value from a ZSET.
var zpopScript = redis.NewScript(1, `
    local r = redis.call('ZRANGE', KEYS[1], 0, 0)
    if r ~= nil then
        r = r[1]
        redis.call('ZREM', KEYS[1], r)
    end
    return r
`)

// This example implements ZPOP as described at
// http://redis.io/topics/transactions using WATCH/MULTI/EXEC and scripting.
func main() {
	c, err := dial()
	if err != nil {
		fmt.Println(err)
		return
	}
	defer c.Close()

	// Add test data using a pipeline.

	for i, member := range []string{"red", "blue", "green"} {
		c.Send("ZADD", "zset", i, member)
	}
	if _, err := c.Do(""); err != nil {
		fmt.Println(err)
		return
	}

	// Pop using WATCH/MULTI/EXEC

	v, err := zpop(c, "zset")
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(v)

	// Pop using a script.

	v, err = redis.String(zpopScript.Do(c, "zset"))
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(v)

}
Output:
red
blue

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrNil = errors.New("redigo: nil returned")
View Source
var ErrPoolExhausted = errors.New("redigo: connection pool exhausted")

Functions

func Bool

func Bool(reply interface{}, err error) (bool, error)

Bool is a helper that converts a command reply to a boolean. If err is not equal to nil, then Bool returns false, err. Otherwise Bool converts the reply to boolean as follows:

Reply type      Result
integer         value != 0, nil
bulk            strconv.ParseBool(reply)
nil             false, ErrNil
other           false, error
Example
c, err := dial()
if err != nil {
	panic(err)
}
defer c.Close()

c.Do("SET", "foo", 1)
exists, _ := redis.Bool(c.Do("EXISTS", "foo"))
fmt.Printf("%#v\n", exists)
Output:
true

func Bytes

func Bytes(reply interface{}, err error) ([]byte, error)

Bytes is a helper that converts a command reply to a slice of bytes. If err is not equal to nil, then Bytes returns nil, err. Otherwise Bytes converts the reply to a slice of bytes as follows:

Reply type      Result
bulk            reply, nil
string          []byte(reply), nil
nil             nil, ErrNil
other           nil, error

func Float64

func Float64(reply interface{}, err error) (float64, error)

Float64 is a helper that converts a command reply to 64 bit float. If err is not equal to nil, then Float64 returns 0, err. Otherwise, Float64 converts the reply to an int as follows:

Reply type    Result
bulk          parsed reply, nil
nil           0, ErrNil
other         0, error

func Int

func Int(reply interface{}, err error) (int, error)

Int is a helper that converts a command reply to an integer. If err is not equal to nil, then Int returns 0, err. Otherwise, Int converts the reply to an int as follows:

Reply type    Result
integer       int(reply), nil
bulk          parsed reply, nil
nil           0, ErrNil
other         0, error
Example
c, err := dial()
if err != nil {
	panic(err)
}
defer c.Close()

c.Do("SET", "k1", 1)
n, _ := redis.Int(c.Do("GET", "k1"))
fmt.Printf("%#v\n", n)
n, _ = redis.Int(c.Do("INCR", "k1"))
fmt.Printf("%#v\n", n)
Output:
1
2

func Int64

func Int64(reply interface{}, err error) (int64, error)

Int64 is a helper that converts a command reply to 64 bit integer. If err is not equal to nil, then Int returns 0, err. Otherwise, Int64 converts the reply to an int64 as follows:

Reply type    Result
integer       reply, nil
bulk          parsed reply, nil
nil           0, ErrNil
other         0, error

func MultiBulk

func MultiBulk(reply interface{}, err error) ([]interface{}, error)

MultiBulk is deprecated. Use Values.

func Scan added in v0.3.0

func Scan(src []interface{}, dest ...interface{}) ([]interface{}, error)

Scan copies from the multi-bulk src to the values pointed at by dest.

The values pointed at by dest must be an integer, float, boolean, string, or []byte. Scan uses the standard strconv package to convert bulk values to numeric and boolean types.

If a dest value is nil, then the corresponding src value is skipped.

If the multi-bulk value is nil, then the corresponding dest value is not modified.

To enable easy use of Scan in a loop, Scan returns the slice of src following the copied values.

Example
c, err := dial()
if err != nil {
	panic(err)
}
defer c.Close()

c.Send("HMSET", "album:1", "title", "Red", "rating", 5)
c.Send("HMSET", "album:2", "title", "Earthbound", "rating", 1)
c.Send("HMSET", "album:3", "title", "Beat")
c.Send("LPUSH", "albums", "1")
c.Send("LPUSH", "albums", "2")
c.Send("LPUSH", "albums", "3")
values, err := redis.Values(c.Do("SORT", "albums",
	"BY", "album:*->rating",
	"GET", "album:*->title",
	"GET", "album:*->rating"))
if err != nil {
	panic(err)
}

for len(values) > 0 {
	var title string
	rating := -1 // initialize to illegal value to detect nil.
	values, err = redis.Scan(values, &title, &rating)
	if err != nil {
		panic(err)
	}
	if rating == -1 {
		fmt.Println(title, "not-rated")
	} else {
		fmt.Println(title, rating)
	}
}
Output:
Beat not-rated
Earthbound 1
Red 5

func ScanStruct added in v0.3.0

func ScanStruct(src []interface{}, dest interface{}) error

ScanStruct scans a multi-bulk src containing alternating names and values to a struct. The HGETALL and CONFIG GET commands return replies in this format.

ScanStruct uses the struct field name to match values in the response. Use 'redis' field tag to override the name:

Field int `redis:"myName"`

Fields with the tag redis:"-" are ignored.

Integer, float boolean string and []byte fields are supported. Scan uses the standard strconv package to convert bulk values to numeric and boolean types.

If the multi-bulk value is nil, then the corresponding field is not modified.

func String

func String(reply interface{}, err error) (string, error)

String is a helper that converts a command reply to a string. If err is not equal to nil, then String returns "", err. Otherwise String converts the reply to a string as follows:

Reply type      Result
bulk            string(reply), nil
string          reply, nil
nil             "",  ErrNil
other           "",  error
Example
c, err := dial()
if err != nil {
	panic(err)
}
defer c.Close()

c.Do("SET", "hello", "world")
s, err := redis.String(c.Do("GET", "hello"))
fmt.Printf("%#v\n", s)
Output:
"world"

func Strings

func Strings(reply interface{}, err error) ([]string, error)

Strings is a helper that converts a multi-bulk command reply to a []string. If err is not equal to nil, then Strings returns nil, err. If one if the multi-bulk items is not a bulk value or nil, then Strings returns an error.

func Values

func Values(reply interface{}, err error) ([]interface{}, error)

Values is a helper that converts a multi-bulk command reply to a []interface{}. If err is not equal to nil, then Values returns nil, err. Otherwise, Multi converts the reply as follows:

Reply type      Result
multi-bulk      reply, nil
nil             nil, ErrNil
other           nil, error

Types

type Args added in v0.3.0

type Args []interface{}

Args is a helper for constructing command arguments from structured values.

Example
c, err := dial()
if err != nil {
	panic(err)
}
defer c.Close()

var p1, p2 struct {
	Title  string `redis:"title"`
	Author string `redis:"author"`
	Body   string `redis:"body"`
}

p1.Title = "Example"
p1.Author = "Gary"
p1.Body = "Hello"

if _, err := c.Do("HMSET", redis.Args{}.Add("id1").AddFlat(&p1)...); err != nil {
	panic(err)
}

m := map[string]string{
	"title":  "Example2",
	"author": "Steve",
	"body":   "Map",
}

if _, err := c.Do("HMSET", redis.Args{}.Add("id2").AddFlat(m)...); err != nil {
	panic(err)
}

for _, id := range []string{"id1", "id2"} {

	v, err := redis.Values(c.Do("HGETALL", id))
	if err != nil {
		panic(err)
	}

	if err := redis.ScanStruct(v, &p2); err != nil {
		panic(err)
	}

	fmt.Printf("%+v\n", p2)
}
Output:
{Title:Example Author:Gary Body:Hello}
{Title:Example2 Author:Steve Body:Map}

func (Args) Add added in v0.3.0

func (args Args) Add(value interface{}) Args

Add returns the result of appending value to args.

func (Args) AddFlat added in v0.3.0

func (args Args) AddFlat(v interface{}) Args

AddFlat returns the result of appending the flattened value of v to args.

Maps are flattened by appending the alternating keys and map values to args.

Slices are flattened by appending the slice elements to args.

Structs are flattened by appending the alternating field names and field values to args. If v is a nil struct pointer, then nothing is appended. The 'redis' field tag overrides struct field names. See ScanStruct for more information on the use of the 'redis' field tag.

Other types are appended to args as is.

type Conn

type Conn interface {
	// Close closes the connection.
	Close() error

	// Err returns a non-nil value if the connection is broken. The returned
	// value is either the first non-nil value returned from the underlying
	// network connection or a protocol parsing error. Applications should
	// close broken connections.
	Err() error

	// Do sends a command to the server and returns the received reply.
	Do(commandName string, args ...interface{}) (reply interface{}, err error)

	// Send writes the command to the client's output buffer.
	Send(commandName string, args ...interface{}) error

	// Flush flushes the output buffer to the Redis server.
	Flush() error

	// Receive receives a single reply from the Redis server
	Receive() (reply interface{}, err error)
}

Conn represents a connection to a Redis server.

func Dial

func Dial(network, address string) (Conn, error)

Dial connects to the Redis server at the given network and address.

func DialTimeout

func DialTimeout(network, address string, connectTimeout, readTimeout, writeTimeout time.Duration) (Conn, error)

DialTimeout acts like Dial but takes timeouts for establishing the connection to the server, writing a command and reading a reply.

func NewConn

func NewConn(netConn net.Conn, readTimeout, writeTimeout time.Duration) Conn

NewConn returns a new Redigo connection for the given net connection.

func NewLoggingConn

func NewLoggingConn(conn Conn, logger *log.Logger, prefix string) Conn

NewLoggingConn returns a logging wrapper around a connection.

type Error

type Error string

Error represents an error returned in a command reply.

func (Error) Error

func (err Error) Error() string

type Message added in v0.3.0

type Message struct {

	// The originating channel.
	Channel string

	// The message data.
	Data []byte
}

Message represents a message notification.

type PMessage added in v0.3.0

type PMessage struct {

	// The matched pattern.
	Pattern string

	// The originating channel.
	Channel string

	// The message data.
	Data []byte
}

PMessage represents a pmessage notification.

type Pool

type Pool struct {

	// Dial is an application supplied function for creating new connections.
	Dial func() (Conn, error)

	// TestOnBorrow is an optional application supplied function for checking
	// the health of an idle connection before the connection is used again by
	// the application. Argument t is the time that the connection was returned
	// to the pool. If the function returns an error, then the connection is
	// closed.
	TestOnBorrow func(c Conn, t time.Time) error

	// Maximum number of idle connections in the pool.
	MaxIdle int

	// Maximum number of connections allocated by the pool at a given time.
	// When zero, there is no limit on the number of connections in the pool.
	MaxActive int

	// Close connections after remaining idle for this duration. If the value
	// is zero, then idle connections are not closed. Applications should set
	// the timeout to a value less than the server's timeout.
	IdleTimeout time.Duration
	// contains filtered or unexported fields
}

Pool maintains a pool of connections. The application calls the Get method to get a connection from the pool and the connection's Close method to return the connection's resources to the pool.

The following example shows how to use a pool in a web application. The application creates a pool at application startup and makes it available to request handlers, possibly using a global variable:

     var server string           // host:port of server
     var password string
     ...

     pool = &redis.Pool{
             MaxIdle: 3,
             IdleTimeout: 240 * time.Second,
             Dial: func () (redis.Conn, error) {
                 c, err := redis.Dial("tcp", server)
                 if err != nil {
                     return nil, err
                 }
                 if err := c.Do("AUTH", password); err != nil {
                     c.Close()
                     return nil, err
                 }
                 return c, err
             },
				TestOnBorrow: func(c redis.Conn, t time.Time) error {
				    _, err := c.Do("PING")
                 return err
			    },
         }

This pool has a maximum of three connections to the server specified by the variable "server". Each connection is authenticated using a password.

A request handler gets a connection from the pool and closes the connection when the handler is done:

conn := pool.Get()
defer conn.Close()
// do something with the connection

func NewPool

func NewPool(newFn func() (Conn, error), maxIdle int) *Pool

NewPool returns a pool that uses newPool to create connections as needed. The pool keeps a maximum of maxIdle idle connections.

func (*Pool) ActiveCount

func (p *Pool) ActiveCount() int

ActiveCount returns the number of active connections in the pool.

func (*Pool) Close

func (p *Pool) Close() error

Close releases the resources used by the pool.

func (*Pool) Get

func (p *Pool) Get() Conn

Get gets a connection from the pool.

type PubSubConn added in v0.3.0

type PubSubConn struct {
	Conn Conn
}

PubSubConn wraps a Conn with convenience methods for subscribers.

Example

Applications can receive pushed messages from one goroutine and manage subscriptions from another goroutine.

c, err := dial()
if err != nil {
	panic(err)
}
defer c.Close()
var wg sync.WaitGroup
wg.Add(2)

psc := redis.PubSubConn{c}

// This goroutine receives and prints pushed notifications from the server.
// The goroutine exits when the connection is unsubscribed from all
// channels or there is an error.
go func() {
	defer wg.Done()
	for {
		switch n := psc.Receive().(type) {
		case redis.Message:
			fmt.Printf("Message: %s %s\n", n.Channel, n.Data)
		case redis.PMessage:
			fmt.Printf("PMessage: %s %s %s\n", n.Pattern, n.Channel, n.Data)
		case redis.Subscription:
			fmt.Printf("Subscription: %s %s %d\n", n.Kind, n.Channel, n.Count)
			if n.Count == 0 {
				return
			}
		case error:
			fmt.Printf("error: %v\n", n)
			return
		}
	}
}()

// This goroutine manages subscriptions for the connection.
go func() {
	defer wg.Done()

	psc.Subscribe("example")
	psc.PSubscribe("p*")

	// The following function calls publish a message using another
	// connection to the Redis server.
	publish("example", "hello")
	publish("example", "world")
	publish("pexample", "foo")
	publish("pexample", "bar")

	// Unsubscribe from all connections. This will cause the receiving
	// goroutine to exit.
	psc.Unsubscribe()
	psc.PUnsubscribe()
}()

wg.Wait()
Output:
Subscription: subscribe example 1
Subscription: psubscribe p* 2
Message: example hello
Message: example world
PMessage: p* pexample foo
PMessage: p* pexample bar
Subscription: unsubscribe example 1
Subscription: punsubscribe p* 0

func (PubSubConn) Close added in v0.3.0

func (c PubSubConn) Close() error

Close closes the connection.

func (PubSubConn) PSubscribe added in v0.3.0

func (c PubSubConn) PSubscribe(channel ...interface{}) error

PSubscribe subscribes the connection to the given patterns.

func (PubSubConn) PUnsubscribe added in v0.3.0

func (c PubSubConn) PUnsubscribe(channel ...interface{}) error

PUnsubscribe unsubscribes the connection from the given patterns, or from all of them if none is given.

func (PubSubConn) Receive added in v0.3.0

func (c PubSubConn) Receive() interface{}

Receive returns a pushed message as a Subscription, Message, PMessage or error. The return value is intended to be used directly in a type switch as illustrated in the PubSubConn example.

func (PubSubConn) Subscribe added in v0.3.0

func (c PubSubConn) Subscribe(channel ...interface{}) error

Subscribe subscribes the connection to the specified channels.

func (PubSubConn) Unsubscribe added in v0.3.0

func (c PubSubConn) Unsubscribe(channel ...interface{}) error

Unsubscribe unsubscribes the connection from the given channels, or from all of them if none is given.

type Script

type Script struct {
	// contains filtered or unexported fields
}

Script encapsulates the source, hash and key count for a Lua script. See http://redis.io/commands/eval for information on scripts in Redis.

func NewScript

func NewScript(keyCount int, src string) *Script

NewScript returns a new script object. If keyCount is greater than or equal to zero, then the count is automatically inserted in the EVAL command argument list. If keyCount is less than zero, then the application supplies the count as the first value in the keysAndArgs argument to the Do, Send and SendHash methods.

func (*Script) Do

func (s *Script) Do(c Conn, keysAndArgs ...interface{}) (interface{}, error)

Do evalutes the script. Under the covers, Do optimistically evaluates the script using the EVALSHA command. If the command fails because the script is not loaded, then Do evaluates the script using the EVAL command (thus causing the script to load).

func (*Script) Load

func (s *Script) Load(c Conn) error

Load loads the script without evaluating it.

func (*Script) Send

func (s *Script) Send(c Conn, keysAndArgs ...interface{}) error

Send evaluates the script without waiting for the reply.

func (*Script) SendHash

func (s *Script) SendHash(c Conn, keysAndArgs ...interface{}) error

SendHash evaluates the script without waiting for the reply. The script is evaluated with the EVALSHA command. The application must ensure that the script is loaded by a previous call to Send, Do or Load methods.

type Subscription added in v0.3.0

type Subscription struct {

	// Kind is "subscribe", "unsubscribe", "psubscribe" or "punsubscribe"
	Kind string

	// The channel that was changed.
	Channel string

	// The current number of subscriptions for connection.
	Count int
}

Subscribe represents a subscribe or unsubscribe notification.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL