Documentation ¶
Overview ¶
Package redis is a client for the Redis database.
The Redigo FAQ (https://github.com/garyburd/redigo/wiki/FAQ) contains more documentation about this package.
Connections ¶
The Conn interface is the primary interface for working with Redis. Applications create connections by calling the Dial, DialWithTimeout or NewConn functions. In the future, functions will be added for creating sharded and other types of connections.
The application must call the connection Close method when the application is done with the connection.
Executing Commands ¶
The Conn interface has a generic method for executing Redis commands:
Do(commandName string, args ...interface{}) (reply interface{}, err error)
The Redis command reference (http://redis.io/commands) lists the available commands. An example of using the Redis APPEND command is:
n, err := conn.Do("APPEND", "key", "value")
The Do method converts command arguments to binary strings for transmission to the server as follows:
Go Type Conversion []byte Sent as is string Sent as is int, int64 strconv.FormatInt(v) float64 strconv.FormatFloat(v, 'g', -1, 64) bool true -> "1", false -> "0" nil "" all other types fmt.Print(v)
Redis command reply types are represented using the following Go types:
Redis type Go type error redis.Error integer int64 simple string string bulk string []byte or nil if value not present. array []interface{} or nil if value not present.
Use type assertions or the reply helper functions to convert from interface{} to the specific Go type for the command result.
Pipelining ¶
Connections support pipelining using the Send, Flush and Receive methods.
Send(commandName string, args ...interface{}) error Flush() error Receive() (reply interface{}, err error)
Send writes the command to the connection's output buffer. Flush flushes the connection's output buffer to the server. Receive reads a single reply from the server. The following example shows a simple pipeline.
c.Send("SET", "foo", "bar") c.Send("GET", "foo") c.Flush() c.Receive() // reply from SET v, err = c.Receive() // reply from GET
The Do method combines the functionality of the Send, Flush and Receive methods. The Do method starts by writing the command and flushing the output buffer. Next, the Do method receives all pending replies including the reply for the command just sent by Do. If any of the received replies is an error, then Do returns the error. If there are no errors, then Do returns the last reply. If the command argument to the Do method is "", then the Do method will flush the output buffer and receive pending replies without sending a command.
Use the Send and Do methods to implement pipelined transactions.
c.Send("MULTI") c.Send("INCR", "foo") c.Send("INCR", "bar") r, err := c.Do("EXEC") fmt.Println(r) // prints [1, 1]
Concurrency ¶
Connections do not support concurrent calls to the write methods (Send, Flush) or concurrent calls to the read method (Receive). Connections do allow a concurrent reader and writer.
Because the Do method combines the functionality of Send, Flush and Receive, the Do method cannot be called concurrently with the other methods.
For full concurrent access to Redis, use the thread-safe Pool to get and release connections from within a goroutine.
Publish and Subscribe ¶
Use the Send, Flush and Receive methods to implement Pub/Sub subscribers.
c.Send("SUBSCRIBE", "example") c.Flush() for { reply, err := c.Receive() if err != nil { return err } // process pushed message }
The PubSubConn type wraps a Conn with convenience methods for implementing subscribers. The Subscribe, PSubscribe, Unsubscribe and PUnsubscribe methods send and flush a subscription management command. The receive method converts a pushed message to convenient types for use in a type switch.
psc := redis.PubSubConn{c} psc.Subscribe("example") for { switch v := psc.Receive().(type) { case redis.Message: fmt.Printf("%s: message: %s\n", v.Channel, v.Data) case redis.Subscription: fmt.Printf("%s: %s %d\n", v.Channel, v.Kind, v.Count) case error: return v } }
Reply Helpers ¶
The Bool, Int, Bytes, String, Strings and Values functions convert a reply to a value of a specific type. To allow convenient wrapping of calls to the connection Do and Receive methods, the functions take a second argument of type error. If the error is non-nil, then the helper function returns the error. If the error is nil, the function converts the reply to the specified type:
exists, err := redis.Bool(c.Do("EXISTS", "foo")) if err != nil { // handle error return from c.Do or type conversion error. }
The Scan function converts elements of a array reply to Go types:
var value1 int var value2 string reply, err := redis.Values(c.Do("MGET", "key1", "key2")) if err != nil { // handle error } if _, err := redis.Scan(reply, &value1, &value2); err != nil { // handle error }
Index ¶
- Constants
- Variables
- func Bool(reply interface{}, err error) (bool, error)
- func ByteSlices(reply interface{}, err error) ([][]byte, error)
- func Bytes(reply interface{}, err error) ([]byte, error)
- func Float64(reply interface{}, err error) (float64, error)
- func Int(reply interface{}, err error) (int, error)
- func Int64(reply interface{}, err error) (int64, error)
- func Int64Map(result interface{}, err error) (map[string]int64, error)
- func Int64s(reply interface{}, err error) ([]int64, error)
- func IntMap(result interface{}, err error) (map[string]int, error)
- func Ints(reply interface{}, err error) ([]int, error)
- func MultiBulk(reply interface{}, err error) ([]interface{}, error)deprecated
- func Scan(src []interface{}, dest ...interface{}) ([]interface{}, error)
- func ScanSlice(src []interface{}, dest interface{}, fieldNames ...string) error
- func ScanStruct(src []interface{}, dest interface{}) error
- func String(reply interface{}, err error) (string, error)
- func StringMap(result interface{}, err error) (map[string]string, error)
- func Strings(reply interface{}, err error) ([]string, error)
- func Uint64(reply interface{}, err error) (uint64, error)
- func Values(reply interface{}, err error) ([]interface{}, error)
- type Args
- type CommandInfo
- type Config
- type Conn
- func Dial(network, address string, options ...DialOption) (Conn, error)
- func DialTimeout(network, address string, ...) (Conn, error)deprecated
- func DialURL(rawurl string, options ...DialOption) (Conn, error)
- func NewConn(c *Config) (cn Conn, err error)
- func NewLoggingConn(conn Conn, logger *log.Logger, prefix string) Conn
- type DialOption
- func DialConnectTimeout(d time.Duration) DialOption
- func DialDatabase(db int) DialOption
- func DialNetDial(dial func(network, addr string) (net.Conn, error)) DialOption
- func DialPassword(password string) DialOption
- func DialReadTimeout(d time.Duration) DialOption
- func DialWriteTimeout(d time.Duration) DialOption
- type Error
- type Message
- type MockErr
- func (m MockErr) Close() error
- func (m MockErr) Do(commandName string, args ...interface{}) (interface{}, error)
- func (m MockErr) Err() error
- func (m MockErr) Flush() error
- func (m MockErr) Receive() (interface{}, error)
- func (m MockErr) Send(commandName string, args ...interface{}) error
- func (m MockErr) WithContext(context.Context) Conn
- type PMessage
- type Pipeliner
- type Pong
- type Pool
- type PubSubConn
- func (c PubSubConn) Close() error
- func (c PubSubConn) PSubscribe(channel ...interface{}) error
- func (c PubSubConn) PUnsubscribe(channel ...interface{}) error
- func (c PubSubConn) Ping(data string) error
- func (c PubSubConn) Receive() interface{}
- func (c PubSubConn) Subscribe(channel ...interface{}) error
- func (c PubSubConn) Unsubscribe(channel ...interface{}) error
- type Redis
- type Replies
- type Script
- type Subscription
Examples ¶
Constants ¶
const ( WatchState = 1 << iota MultiState SubscribeState MonitorState )
redis state
Variables ¶
var ErrNil = errors.New("redigo: nil returned")
ErrNil indicates that a reply value is nil.
var (
ErrNoReply = errors.New("redis: no reply in result set")
)
Functions ¶
func Bool ¶
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 string strconv.ParseBool(reply) nil false, ErrNil other false, error
Example ¶
c, err := dial() if err != nil { fmt.Println(err) return } defer c.Close() c.Do("SET", "foo", 1) exists, _ := Bool(c.Do("EXISTS", "foo")) fmt.Printf("%#v\n", exists)
Output: true
func ByteSlices ¶
ByteSlices is a helper that converts an array command reply to a [][]byte. If err is not equal to nil, then ByteSlices returns nil, err. Nil array items are stay nil. ByteSlices returns an error if an array item is not a bulk string or nil.
func Bytes ¶
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 string reply, nil simple string []byte(reply), nil nil nil, ErrNil other nil, error
func Float64 ¶
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 string parsed reply, nil nil 0, ErrNil other 0, error
func Int ¶
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 string parsed reply, nil nil 0, ErrNil other 0, error
Example ¶
c, err := dial() if err != nil { fmt.Println(err) return } defer c.Close() c.Do("SET", "k1", 1) n, _ := Int(c.Do("GET", "k1")) fmt.Printf("%#v\n", n) n, _ = Int(c.Do("INCR", "k1")) fmt.Printf("%#v\n", n)
Output: 1 2
func Int64 ¶
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 string parsed reply, nil nil 0, ErrNil other 0, error
func Int64Map ¶
Int64Map is a helper that converts an array of strings (alternating key, value) into a map[string]int64. The HGETALL commands return replies in this format. Requires an even number of values in result.
func Int64s ¶
Int64s is a helper that converts an array command reply to a []int64. If err is not equal to nil, then Int64s returns nil, err.
func IntMap ¶
IntMap is a helper that converts an array of strings (alternating key, value) into a map[string]int. The HGETALL commands return replies in this format. Requires an even number of values in result.
func Ints ¶
Ints is a helper that converts an array command reply to a []int. If err is not equal to nil, then Ints returns nil, err.
Example ¶
c, err := dial() if err != nil { fmt.Println(err) return } defer c.Close() c.Do("SADD", "set_with_integers", 4, 5, 6) ints, _ := Ints(c.Do("SMEMBERS", "set_with_integers")) fmt.Printf("%#v\n", ints)
Output: []int{4, 5, 6}
func Scan ¶
func Scan(src []interface{}, dest ...interface{}) ([]interface{}, error)
Scan copies from src to the values pointed at by dest.
The values pointed at by dest must be an integer, float, boolean, string, []byte, interface{} or slices of these types. Scan uses the standard strconv package to convert bulk strings to numeric and boolean types.
If a dest value is nil, then the corresponding src value is skipped.
If a src element 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 { fmt.Println(err) return } 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 := Values(c.Do("SORT", "albums", "BY", "album:*->rating", "GET", "album:*->title", "GET", "album:*->rating")) if err != nil { fmt.Println(err) return } for len(values) > 0 { var title string rating := -1 // initialize to illegal value to detect nil. values, err = Scan(values, &title, &rating) if err != nil { fmt.Println(err) return } if rating == -1 { fmt.Println(title, "not-rated") } else { fmt.Println(title, rating) } }
Output: Beat not-rated Earthbound 1 Red 5
func ScanSlice ¶
ScanSlice scans src to the slice pointed to by dest. The elements the dest slice must be integer, float, boolean, string, struct or pointer to struct values.
Struct fields must be integer, float, boolean or string values. All struct fields are used unless a subset is specified using fieldNames.
Example ¶
c, err := dial() if err != nil { fmt.Println(err) return } 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", "rating", 4) c.Send("LPUSH", "albums", "1") c.Send("LPUSH", "albums", "2") c.Send("LPUSH", "albums", "3") values, err := Values(c.Do("SORT", "albums", "BY", "album:*->rating", "GET", "album:*->title", "GET", "album:*->rating")) if err != nil { fmt.Println(err) return } var albums []struct { Title string Rating int } if err := ScanSlice(values, &albums); err != nil { fmt.Println(err) return } fmt.Printf("%v\n", albums)
Output: [{Earthbound 1} {Beat 4} {Red 5}]
func ScanStruct ¶
func ScanStruct(src []interface{}, dest interface{}) error
ScanStruct scans alternating names and values from src to a struct. The HGETALL and CONFIG GET commands return replies in this format.
ScanStruct uses exported field names 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 string values to numeric and boolean types.
If a src element is nil, then the corresponding field is not modified.
func String ¶
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 string(reply), nil simple string reply, nil nil "", ErrNil other "", error
Example ¶
c, err := dial() if err != nil { fmt.Println(err) return } defer c.Close() c.Do("SET", "hello", "world") s, _ := String(c.Do("GET", "hello")) fmt.Printf("%#v", s)
Output: "world"
func StringMap ¶
StringMap is a helper that converts an array of strings (alternating key, value) into a map[string]string. The HGETALL and CONFIG GET commands return replies in this format. Requires an even number of values in result.
func Strings ¶
Strings is a helper that converts an array command reply to a []string. If err is not equal to nil, then Strings returns nil, err. Nil array items are converted to "" in the output slice. Strings returns an error if an array item is not a bulk string or nil.
func Uint64 ¶
Uint64 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 string parsed reply, nil nil 0, ErrNil other 0, error
Types ¶
type Args ¶
type Args []interface{}
Args is a helper for constructing command arguments from structured values.
Example ¶
c, err := dial() if err != nil { fmt.Println(err) return } 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", Args{}.Add("id1").AddFlat(&p1)...); err != nil { fmt.Println(err) return } m := map[string]string{ "title": "Example2", "author": "Steve", "body": "Map", } if _, err := c.Do("HMSET", Args{}.Add("id2").AddFlat(m)...); err != nil { fmt.Println(err) return } for _, id := range []string{"id1", "id2"} { v, err := Values(c.Do("HGETALL", id)) if err != nil { fmt.Println(err) return } if err := ScanStruct(v, &p2); err != nil { fmt.Println(err) return } fmt.Printf("%+v\n", p2) }
Output: {Title:Example Author:Gary Body:Hello} {Title:Example2 Author:Steve Body:Map}
func (Args) AddFlat ¶
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 names and values of exported fields 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 CommandInfo ¶
type CommandInfo struct {
Set, Clear int
}
CommandInfo command info.
func LookupCommandInfo ¶
func LookupCommandInfo(commandName string) CommandInfo
LookupCommandInfo get command info.
type Config ¶
type Config struct { *pool.Config Name string // redis name, for trace Proto string Addr string Auth string Db int DialTimeout xtime.Duration ReadTimeout xtime.Duration WriteTimeout xtime.Duration SlowLog xtime.Duration }
Config client settings.
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) // WithContext returns Conn with the input ctx. WithContext(ctx context.Context) Conn }
Conn represents a connection to a Redis server.
func Dial ¶
func Dial(network, address string, options ...DialOption) (Conn, error)
Dial connects to the Redis server at the given network and address using the specified options.
Example ¶
Connect to local instance of Redis running on the default port.
c, err := Dial("tcp", ":6379") if err != nil { // handle error } defer c.Close()
Output:
func DialTimeout
deprecated
func DialURL ¶
func DialURL(rawurl string, options ...DialOption) (Conn, error)
DialURL connects to a Redis server at the given URL using the Redis URI scheme. URLs should follow the draft IANA specification for the scheme (https://www.iana.org/assignments/uri-schemes/prov/redis).
Example ¶
Connect to remote instance of Redis using a URL.
c, err := DialURL(os.Getenv("REDIS_URL")) if err != nil { // handle connection error } defer c.Close()
Output:
type DialOption ¶
type DialOption struct {
// contains filtered or unexported fields
}
DialOption specifies an option for dialing a Redis server.
func DialConnectTimeout ¶
func DialConnectTimeout(d time.Duration) DialOption
DialConnectTimeout specifies the timeout for connecting to the Redis server.
func DialDatabase ¶
func DialDatabase(db int) DialOption
DialDatabase specifies the database to select when dialing a connection.
func DialNetDial ¶
func DialNetDial(dial func(network, addr string) (net.Conn, error)) DialOption
DialNetDial specifies a custom dial function for creating TCP connections. If this option is left out, then net.Dial is used. DialNetDial overrides DialConnectTimeout.
func DialPassword ¶
func DialPassword(password string) DialOption
DialPassword specifies the password to use when connecting to the Redis server.
func DialReadTimeout ¶
func DialReadTimeout(d time.Duration) DialOption
DialReadTimeout specifies the timeout for reading a single command reply.
func DialWriteTimeout ¶
func DialWriteTimeout(d time.Duration) DialOption
DialWriteTimeout specifies the timeout for writing a single command.
type PMessage ¶
type PMessage struct { // The matched pattern. Pattern string // The originating channel. Channel string // The message data. Data []byte }
PMessage represents a pmessage notification.
type Pipeliner ¶
type Pipeliner interface { // Send writes the command to the client's output buffer. Send(commandName string, args ...interface{}) // Exec executes all commands and get replies. Exec(ctx context.Context) (rs *Replies, err error) }
Example ¶
r := NewRedis(testConfig) defer r.Close() pip := r.Pipeline() pip.Send("SET", "hello", "world") pip.Send("GET", "hello") replies, err := pip.Exec(context.TODO()) if err != nil { fmt.Printf("%#v\n", err) } for replies.Next() { s, err := String(replies.Scan()) if err != nil { fmt.Printf("err %#v\n", err) } fmt.Printf("%#v\n", s) }
Output: "OK" "world"
type Pool ¶
Pool .
func (*Pool) Get ¶
Get gets a connection. The application must close the returned connection. This method always returns a valid connection so that applications can defer error handling to the first use of the connection. If there is an error getting an underlying connection, then the connection Err, Do, Send, Flush and Receive methods return that error.
type PubSubConn ¶
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 { fmt.Println(err) return } defer c.Close() var wg sync.WaitGroup wg.Add(2) psc := PubSubConn{Conn: 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 Message: fmt.Printf("Message: %s %s\n", n.Channel, n.Data) case PMessage: fmt.Printf("PMessage: %s %s %s\n", n.Pattern, n.Channel, n.Data) case 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) PSubscribe ¶
func (c PubSubConn) PSubscribe(channel ...interface{}) error
PSubscribe subscribes the connection to the given patterns.
func (PubSubConn) PUnsubscribe ¶
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) Ping ¶
func (c PubSubConn) Ping(data string) error
Ping sends a PING to the server with the specified data.
func (PubSubConn) Receive ¶
func (c PubSubConn) Receive() interface{}
Receive returns a pushed message as a Subscription, Message, PMessage, Pong or error. The return value is intended to be used directly in a type switch as illustrated in the PubSubConn example.
func (PubSubConn) Subscribe ¶
func (c PubSubConn) Subscribe(channel ...interface{}) error
Subscribe subscribes the connection to the specified channels.
func (PubSubConn) Unsubscribe ¶
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 Redis ¶
type Redis struct {
// contains filtered or unexported fields
}
func NewRedis ¶
func NewRedis(c *Config, options ...DialOption) *Redis
func (*Redis) Do ¶
func (r *Redis) Do(ctx context.Context, commandName string, args ...interface{}) (reply interface{}, err error)
Do gets a new conn from pool, then execute Do with this conn, finally close this conn. ATTENTION: Don't use this method with transaction command like MULTI etc. Because every Do will close conn automatically, use r.Conn to get a raw conn for this situation.
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.
Example ¶
c, err := Dial("tcp", ":6379") if err != nil { // handle error } defer c.Close() // Initialize a package-level variable with a script. var getScript = NewScript(1, `return call('get', KEYS[1])`) // In a function, use the script Do method to evaluate the script. The Do // method optimistically uses the EVALSHA command. If the script is not // loaded, then the Do method falls back to the EVAL command. if _, err = getScript.Do(c, "foo"); err != nil { // handle error }
Output:
func NewScript ¶
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 ¶
Do evaluates 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).
type Subscription ¶
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 }
Subscription represents a subscribe or unsubscribe notification.