diff --git a/README.md b/README.md index 639dd36..1d1372b 100644 --- a/README.md +++ b/README.md @@ -2,204 +2,3 @@ New version =========== Make sure to check new version of the client that got better API and timeout support: https://github.com/vmihailenco/redis/tree/master/v2 - -Redis client for Golang -======================= - -Supports: - -- Redis 2.6 commands except QUIT, MONITOR, SLOWLOG and SYNC. -- Pub/sub. -- Transactions. -- Pipelining. -- Connection pool. -- TLS connections. -- Thread safety. - -API docs: http://godoc.org/github.com/vmihailenco/redis - -Installation ------------- - -Install: - - go get github.com/vmihailenco/redis - -Getting started ---------------- - -Let's start with connecting to Redis using TCP: - -```go -password := "" // no password set -db := int64(-1) // use default DB -client := redis.NewTCPClient("localhost:6379", password, db) -defer client.Close() - -ping := client.Ping() -fmt.Println(ping.Err(), ping.Val()) -// Output: PONG -``` -or using Unix socket: - -```go -client := redis.NewUnixClient("/tmp/redis.sock", "", -1) -defer client.Close() - -ping := client.Ping() -fmt.Println(ping.Err(), ping.Val()) -// Output: PONG -``` -Then we can start sending commands: - -```go -set := client.Set("foo", "bar") -fmt.Println(set.Err(), set.Val()) - -get := client.Get("foo") -fmt.Println(get.Err(), get.Val()) - -// Output: OK -// bar -``` - -We can also pipeline two commands together: - -```go -var set *redis.StatusReq -var get *redis.StringReq -reqs, err := client.Pipelined(func(c *redis.PipelineClient) { - set = c.Set("key1", "hello1") - get = c.Get("key2") -}) -fmt.Println(err, reqs) -fmt.Println(set) -fmt.Println(get) -// Output: [SET key1 hello1: OK GET key2: (nil)] -// SET key1 hello1: OK -// GET key2: (nil) -``` -or: - -```go -var set *redis.StatusReq -var get *redis.StringReq -reqs, err := client.Pipelined(func(c *redis.PipelineClient) { - set = c.Set("key1", "hello1") - get = c.Get("key2") -}) -fmt.Println(err, reqs) -fmt.Println(set) -fmt.Println(get) -// Output: [SET key1 hello1 GET key2] -// SET key1 hello1 -// GET key2 -``` - -We can also send several commands in transaction: - -```go -func transaction(multi *redis.MultiClient) ([]redis.Req, error) { - get := multi.Get("key") - if err := get.Err(); err != nil && err != redis.Nil { - return nil, err - } - - val, _ := strconv.ParseInt(get.Val(), 10, 64) - - reqs, err := multi.Exec(func() { - multi.Set("key", strconv.FormatInt(val+1, 10)) - }) - // Transaction failed. Repeat. - if err == redis.Nil { - return transaction(multi) - } - return reqs, err -} - -multi, err := client.MultiClient() -_ = err -defer multi.Close() - -watch := multi.Watch("key") -_ = watch.Err() - -reqs, err := transaction(multi) -fmt.Println(err, reqs) - -// Output: [SET key 1: OK] -``` - -To subscribe to the channel: - -```go -pubsub, err := client.PubSubClient() -defer pubsub.Close() - -ch, err := pubsub.Subscribe("mychannel") -_ = err - -subscribeMsg := <-ch -fmt.Println(subscribeMsg.Err, subscribeMsg.Name) - -pub := client.Publish("mychannel", "hello") -_ = pub.Err() - -msg := <-ch -fmt.Println(msg.Err, msg.Message) - -// Output: subscribe -// hello -``` - -You can also write custom commands: - -```go -func Get(client *redis.Client, key string) *redis.StringReq { - req := redis.NewStringReq("GET", key) - client.Process(req) - return req -} - -get := Get(client, "key_does_not_exist") -fmt.Println(get.Err(), get.Val()) -// Output: (nil) -``` - -Client uses connection pool to send commands. You can change maximum number of connections with: - -```go -client.ConnPool.(*redis.MultiConnPool).MaxCap = 1 -``` - -Look and feel -------------- - -Some corner cases: - - SORT list LIMIT 0 2 ASC - client.Sort("list", redis.Sort{Offset: 0, Count: 2, Order: "ASC"}) - - ZRANGEBYSCORE zset -inf +inf WITHSCORES LIMIT 0 2 - client.ZRangeByScoreWithScores("zset", "-inf", "+inf", 0, 2) - - ZINTERSTORE out 2 zset1 zset2 WEIGHTS 2 3 AGGREGATE SUM - client.ZInterStore("out", redis.ZStore{Weights: []int64{2, 3}}, "zset1", "zset2") - - EVAL "return {KEYS[1],ARGV[1]}" 1 "key" "hello" - client.Eval("return {KEYS[1],ARGV[1]}", []string{"key"}, []string{"hello"}) - -Contributing ------------- - -Configure Redis to allow maximum 10 clients: - - maxclients 10 - -Run tests: - - go test -gocheck.v - -Run benchmarks: - - go test -gocheck.b diff --git a/v2/README.md b/v2/README.md index 622a39c..8bd8d06 100644 --- a/v2/README.md +++ b/v2/README.md @@ -3,7 +3,7 @@ Redis client for Golang [![Build Status](https://travis-ci.org/vmihailenco/redis Supports: -- Redis 2.6 commands except QUIT, MONITOR, SLOWLOG and SYNC. +- Redis 2.8 commands except QUIT, MONITOR, SLOWLOG and SYNC. - Pub/sub. - Transactions. - Pipelining. @@ -27,195 +27,6 @@ Upgrading from previous version Type system should catch most changes. But you have to manually change `SetEx`, `PSetEx`, `Expire` and `PExpire` to use `time.Duration` instead of `int64`. -Getting started ---------------- - -Let's start with connecting to Redis using TCP: - -```go -client := redis.NewTCPClient(&redis.Options{ - Addr: "localhost:6379", - Password: "", // no password set - DB: 0, // use default DB -}) -defer client.Close() - -ping := client.Ping() -fmt.Println(ping.Val(), ping.Err()) -// Output: PONG -``` - -or using Unix socket: - -```go -client := redis.NewUnixClient(&redis.Options{ - Addr: "/tmp/redis.sock", -}) -defer client.Close() - -ping := client.Ping() -fmt.Println(ping.Val(), ping.Err()) -// Output: PONG -``` - -Then we can start sending commands: - -```go -set := client.Set("foo", "bar") -fmt.Println(set.Err(), set.Val()) - -get := client.Get("foo") -fmt.Println(get.Err(), get.Val()) - -// Output: OK -// bar -``` - -We can also pipeline two commands together: - -```go -pipeline := client.Pipeline() -set := pipeline.Set("key1", "hello1") -get := pipeline.Get("key2") -cmds, err := pipeline.Exec() -fmt.Println(cmds, err) -fmt.Println(set) -fmt.Println(get) -// Output: [SET key1 hello1: OK GET key2: (nil)] (nil) -// SET key1 hello1: OK -// GET key2: (nil) -``` - -or: - -```go -client := redis.NewTCPClient(&redis.Options{ - Addr: ":6379", -}) -defer client.Close() - -cmds, err := client.Pipelined(func(c *redis.Pipeline) { - c.Set("key1", "hello1") - c.Get("key2") -}) -fmt.Println(cmds, err) -// Output: [SET key1 hello1: OK GET key2: (nil)] (nil) -``` - -We can also send several commands in transaction: - -```go -incr := func(tx *redis.Multi) ([]redis.Cmder, error) { - get := tx.Get("key") - if err := get.Err(); err != nil && err != redis.Nil { - return nil, err - } - - val, _ := strconv.ParseInt(get.Val(), 10, 64) - - return tx.Exec(func() { - tx.Set("key", strconv.FormatInt(val+1, 10)) - }) -} - -client := redis.NewTCPClient(&redis.Options{ - Addr: ":6379", -}) -defer client.Close() - -client.Del("key") - -tx := client.Multi() -defer tx.Close() - -watch := tx.Watch("key") -_ = watch.Err() - -for { - cmds, err := incr(tx) - if err == redis.TxFailedErr { - continue - } else if err != nil { - panic(err) - } - fmt.Println(cmds, err) - break -} - -// Output: [SET key 1: OK] -``` - -To subscribe to the channel: - -```go -pubsub := client.PubSub() -defer pubsub.Close() - -err := pubsub.Subscribe("mychannel") -_ = err - -msg, err := pubsub.Receive() -fmt.Println(msg, err) - -pub := client.Publish("mychannel", "hello") -_ = pub.Err() - -msg, err = pubsub.Receive() -fmt.Println(msg, err) - -// Output: &{subscribe mychannel 1} -// &{mychannel hello} -``` - -To use Lua scripting: - -```go -client := redis.NewTCPClient(&redis.Options{ - Addr: ":6379", -}) -defer client.Close() - -setnx := redis.NewScript(` - if redis.call("get", KEYS[1]) == false then - redis.call("set", KEYS[1], ARGV[1]) - return 1 - end - return 0 -`) - -run1 := setnx.Run(client, []string{"keynx"}, []string{"foo"}) -fmt.Println(run1.Val().(int64), run1.Err()) - -run2 := setnx.Run(client, []string{"keynx"}, []string{"bar"}) -fmt.Println(run2.Val().(int64), run2.Err()) - -get := client.Get("keynx") -fmt.Println(get) - -// Output: 1 -// 0 -// GET keynx: foo -``` - -You can also write custom commands: - -```go -Get := func(client *redis.Client, key string) *redis.StringCmd { - cmd := redis.NewStringCmd("GET", key) - client.Process(cmd) - return cmd -} - -client := redis.NewTCPClient(&redis.Options{ - Addr: ":6379", -}) -defer client.Close() - -get := Get(client, "key_does_not_exist") -fmt.Printf("%q %s", get.Val(), get.Err()) -// Output: "" (nil) -``` - Look and feel ------------- @@ -237,18 +48,3 @@ Some corner cases: EVAL "return {KEYS[1],ARGV[1]}" 1 "key" "hello" client.Eval("return {KEYS[1],ARGV[1]}", []string{"key"}, []string{"hello"}) - -Contributing ------------- - -Configure Redis to allow maximum 10 clients: - - maxclients 10 - -Run tests: - - go test -gocheck.v - -Run benchmarks: - - go test -gocheck.b diff --git a/v2/example_test.go b/v2/example_test.go index 840f80d..ee4277c 100644 --- a/v2/example_test.go +++ b/v2/example_test.go @@ -23,19 +23,19 @@ func ExampleNewTCPClient() { }) defer client.Close() - ping := client.Ping() - fmt.Println(ping.Val(), ping.Err()) + pong, err := client.Ping().Result() + fmt.Println(pong, err) // Output: PONG } func ExampleClient() { set := client.Set("foo", "bar") - fmt.Println(set.Val(), set.Err()) + fmt.Println(set.Err()) - get := client.Get("hello") - fmt.Printf("%q %s %v", get.Val(), get.Err(), get.Err() == redis.Nil) + v, err := client.Get("hello").Result() + fmt.Printf("%q %s %v", v, err, err == redis.Nil) - // Output: OK + // Output: // "" redis: nil true } @@ -44,10 +44,14 @@ func ExampleClient_Pipelined() { c.Set("key1", "hello1") c.Get("key1") }) + fmt.Println(err) set := cmds[0].(*redis.StatusCmd) + fmt.Println(set) get := cmds[1].(*redis.StringCmd) - fmt.Println(set, get, err) - // Output: SET key1 hello1: OK GET key1: hello1 + fmt.Println(get) + // Output: + // SET key1 hello1: OK + // GET key1: hello1 } func ExamplePipeline() { @@ -65,15 +69,14 @@ func ExamplePipeline() { func ExampleMulti() { incr := func(tx *redis.Multi) ([]redis.Cmder, error) { - get := tx.Get("key") - if err := get.Err(); err != nil && err != redis.Nil { + s, err := tx.Get("key").Result() + if err != nil && err != redis.Nil { return nil, err } - - val, _ := strconv.ParseInt(get.Val(), 10, 64) + n, _ := strconv.ParseInt(s, 10, 64) return tx.Exec(func() { - tx.Set("key", strconv.FormatInt(val+1, 10)) + tx.Set("key", strconv.FormatInt(n+1, 10)) }) } @@ -128,11 +131,11 @@ func ExampleScript() { return 0 `) - run1 := setnx.Run(client, []string{"keynx"}, []string{"foo"}) - fmt.Println(run1.Val().(int64), run1.Err()) + v1, err := setnx.Run(client, []string{"keynx"}, []string{"foo"}).Result() + fmt.Println(v1.(int64), err) - run2 := setnx.Run(client, []string{"keynx"}, []string{"bar"}) - fmt.Println(run2.Val().(int64), run2.Err()) + v2, err := setnx.Run(client, []string{"keynx"}, []string{"bar"}).Result() + fmt.Println(v2.(int64), err) get := client.Get("keynx") fmt.Println(get) @@ -149,7 +152,7 @@ func Example_customCommand() { return cmd } - get := Get(client, "key_does_not_exist") - fmt.Printf("%q %s", get.Val(), get.Err()) + v, err := Get(client, "key_does_not_exist").Result() + fmt.Printf("%q %s", v, err) // Output: "" redis: nil }