example_test.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. package redis_test
  2. import (
  3. "errors"
  4. "fmt"
  5. "sync"
  6. "time"
  7. "github.com/go-redis/redis"
  8. )
  9. var redisdb *redis.Client
  10. func init() {
  11. redisdb = redis.NewClient(&redis.Options{
  12. Addr: ":6379",
  13. DialTimeout: 10 * time.Second,
  14. ReadTimeout: 30 * time.Second,
  15. WriteTimeout: 30 * time.Second,
  16. PoolSize: 10,
  17. PoolTimeout: 30 * time.Second,
  18. })
  19. }
  20. func ExampleNewClient() {
  21. redisdb := redis.NewClient(&redis.Options{
  22. Addr: "localhost:6379", // use default Addr
  23. Password: "", // no password set
  24. DB: 0, // use default DB
  25. })
  26. pong, err := redisdb.Ping().Result()
  27. fmt.Println(pong, err)
  28. // Output: PONG <nil>
  29. }
  30. func ExampleParseURL() {
  31. opt, err := redis.ParseURL("redis://:qwerty@localhost:6379/1")
  32. if err != nil {
  33. panic(err)
  34. }
  35. fmt.Println("addr is", opt.Addr)
  36. fmt.Println("db is", opt.DB)
  37. fmt.Println("password is", opt.Password)
  38. // Create client as usually.
  39. _ = redis.NewClient(opt)
  40. // Output: addr is localhost:6379
  41. // db is 1
  42. // password is qwerty
  43. }
  44. func ExampleNewFailoverClient() {
  45. // See http://redis.io/topics/sentinel for instructions how to
  46. // setup Redis Sentinel.
  47. redisdb := redis.NewFailoverClient(&redis.FailoverOptions{
  48. MasterName: "master",
  49. SentinelAddrs: []string{":26379"},
  50. })
  51. redisdb.Ping()
  52. }
  53. func ExampleNewClusterClient() {
  54. // See http://redis.io/topics/cluster-tutorial for instructions
  55. // how to setup Redis Cluster.
  56. redisdb := redis.NewClusterClient(&redis.ClusterOptions{
  57. Addrs: []string{":7000", ":7001", ":7002", ":7003", ":7004", ":7005"},
  58. })
  59. redisdb.Ping()
  60. }
  61. // Following example creates a cluster from 2 master nodes and 2 slave nodes
  62. // without using cluster mode or Redis Sentinel.
  63. func ExampleNewClusterClient_manualSetup() {
  64. // clusterSlots returns cluster slots information.
  65. // It can use service like ZooKeeper to maintain configuration information
  66. // and Cluster.ReloadState to manually trigger state reloading.
  67. clusterSlots := func() ([]redis.ClusterSlot, error) {
  68. slots := []redis.ClusterSlot{
  69. // First node with 1 master and 1 slave.
  70. {
  71. Start: 0,
  72. End: 8191,
  73. Nodes: []redis.ClusterNode{{
  74. Addr: ":7000", // master
  75. }, {
  76. Addr: ":8000", // 1st slave
  77. }},
  78. },
  79. // Second node with 1 master and 1 slave.
  80. {
  81. Start: 8192,
  82. End: 16383,
  83. Nodes: []redis.ClusterNode{{
  84. Addr: ":7001", // master
  85. }, {
  86. Addr: ":8001", // 1st slave
  87. }},
  88. },
  89. }
  90. return slots, nil
  91. }
  92. redisdb := redis.NewClusterClient(&redis.ClusterOptions{
  93. ClusterSlots: clusterSlots,
  94. RouteRandomly: true,
  95. })
  96. redisdb.Ping()
  97. // ReloadState reloads cluster state. It calls ClusterSlots func
  98. // to get cluster slots information.
  99. err := redisdb.ReloadState()
  100. if err != nil {
  101. panic(err)
  102. }
  103. }
  104. func ExampleNewRing() {
  105. redisdb := redis.NewRing(&redis.RingOptions{
  106. Addrs: map[string]string{
  107. "shard1": ":7000",
  108. "shard2": ":7001",
  109. "shard3": ":7002",
  110. },
  111. })
  112. redisdb.Ping()
  113. }
  114. func ExampleClient() {
  115. err := redisdb.Set("key", "value", 0).Err()
  116. if err != nil {
  117. panic(err)
  118. }
  119. val, err := redisdb.Get("key").Result()
  120. if err != nil {
  121. panic(err)
  122. }
  123. fmt.Println("key", val)
  124. val2, err := redisdb.Get("missing_key").Result()
  125. if err == redis.Nil {
  126. fmt.Println("missing_key does not exist")
  127. } else if err != nil {
  128. panic(err)
  129. } else {
  130. fmt.Println("missing_key", val2)
  131. }
  132. // Output: key value
  133. // missing_key does not exist
  134. }
  135. func ExampleClient_Set() {
  136. // Last argument is expiration. Zero means the key has no
  137. // expiration time.
  138. err := redisdb.Set("key", "value", 0).Err()
  139. if err != nil {
  140. panic(err)
  141. }
  142. // key2 will expire in an hour.
  143. err = redisdb.Set("key2", "value", time.Hour).Err()
  144. if err != nil {
  145. panic(err)
  146. }
  147. }
  148. func ExampleClient_Incr() {
  149. result, err := redisdb.Incr("counter").Result()
  150. if err != nil {
  151. panic(err)
  152. }
  153. fmt.Println(result)
  154. // Output: 1
  155. }
  156. func ExampleClient_BLPop() {
  157. if err := redisdb.RPush("queue", "message").Err(); err != nil {
  158. panic(err)
  159. }
  160. // use `redisdb.BLPop(0, "queue")` for infinite waiting time
  161. result, err := redisdb.BLPop(1*time.Second, "queue").Result()
  162. if err != nil {
  163. panic(err)
  164. }
  165. fmt.Println(result[0], result[1])
  166. // Output: queue message
  167. }
  168. func ExampleClient_Scan() {
  169. redisdb.FlushDB()
  170. for i := 0; i < 33; i++ {
  171. err := redisdb.Set(fmt.Sprintf("key%d", i), "value", 0).Err()
  172. if err != nil {
  173. panic(err)
  174. }
  175. }
  176. var cursor uint64
  177. var n int
  178. for {
  179. var keys []string
  180. var err error
  181. keys, cursor, err = redisdb.Scan(cursor, "key*", 10).Result()
  182. if err != nil {
  183. panic(err)
  184. }
  185. n += len(keys)
  186. if cursor == 0 {
  187. break
  188. }
  189. }
  190. fmt.Printf("found %d keys\n", n)
  191. // Output: found 33 keys
  192. }
  193. func ExampleClient_Pipelined() {
  194. var incr *redis.IntCmd
  195. _, err := redisdb.Pipelined(func(pipe redis.Pipeliner) error {
  196. incr = pipe.Incr("pipelined_counter")
  197. pipe.Expire("pipelined_counter", time.Hour)
  198. return nil
  199. })
  200. fmt.Println(incr.Val(), err)
  201. // Output: 1 <nil>
  202. }
  203. func ExampleClient_Pipeline() {
  204. pipe := redisdb.Pipeline()
  205. incr := pipe.Incr("pipeline_counter")
  206. pipe.Expire("pipeline_counter", time.Hour)
  207. // Execute
  208. //
  209. // INCR pipeline_counter
  210. // EXPIRE pipeline_counts 3600
  211. //
  212. // using one redisdb-server roundtrip.
  213. _, err := pipe.Exec()
  214. fmt.Println(incr.Val(), err)
  215. // Output: 1 <nil>
  216. }
  217. func ExampleClient_TxPipelined() {
  218. var incr *redis.IntCmd
  219. _, err := redisdb.TxPipelined(func(pipe redis.Pipeliner) error {
  220. incr = pipe.Incr("tx_pipelined_counter")
  221. pipe.Expire("tx_pipelined_counter", time.Hour)
  222. return nil
  223. })
  224. fmt.Println(incr.Val(), err)
  225. // Output: 1 <nil>
  226. }
  227. func ExampleClient_TxPipeline() {
  228. pipe := redisdb.TxPipeline()
  229. incr := pipe.Incr("tx_pipeline_counter")
  230. pipe.Expire("tx_pipeline_counter", time.Hour)
  231. // Execute
  232. //
  233. // MULTI
  234. // INCR pipeline_counter
  235. // EXPIRE pipeline_counts 3600
  236. // EXEC
  237. //
  238. // using one redisdb-server roundtrip.
  239. _, err := pipe.Exec()
  240. fmt.Println(incr.Val(), err)
  241. // Output: 1 <nil>
  242. }
  243. func ExampleClient_Watch() {
  244. const routineCount = 100
  245. // Transactionally increments key using GET and SET commands.
  246. increment := func(key string) error {
  247. txf := func(tx *redis.Tx) error {
  248. // get current value or zero
  249. n, err := tx.Get(key).Int()
  250. if err != nil && err != redis.Nil {
  251. return err
  252. }
  253. // actual opperation (local in optimistic lock)
  254. n++
  255. // runs only if the watched keys remain unchanged
  256. _, err = tx.Pipelined(func(pipe redis.Pipeliner) error {
  257. // pipe handles the error case
  258. pipe.Set(key, n, 0)
  259. return nil
  260. })
  261. return err
  262. }
  263. for retries := routineCount; retries > 0; retries-- {
  264. err := redisdb.Watch(txf, key)
  265. if err != redis.TxFailedErr {
  266. return err
  267. }
  268. // optimistic lock lost
  269. }
  270. return errors.New("increment reached maximum number of retries")
  271. }
  272. var wg sync.WaitGroup
  273. wg.Add(routineCount)
  274. for i := 0; i < routineCount; i++ {
  275. go func() {
  276. defer wg.Done()
  277. if err := increment("counter3"); err != nil {
  278. fmt.Println("increment error:", err)
  279. }
  280. }()
  281. }
  282. wg.Wait()
  283. n, err := redisdb.Get("counter3").Int()
  284. fmt.Println("ended with", n, err)
  285. // Output: ended with 100 <nil>
  286. }
  287. func ExamplePubSub() {
  288. pubsub := redisdb.Subscribe("mychannel1")
  289. // Wait for confirmation that subscription is created before publishing anything.
  290. _, err := pubsub.Receive()
  291. if err != nil {
  292. panic(err)
  293. }
  294. // Go channel which receives messages.
  295. ch := pubsub.Channel()
  296. // Publish a message.
  297. err = redisdb.Publish("mychannel1", "hello").Err()
  298. if err != nil {
  299. panic(err)
  300. }
  301. time.AfterFunc(time.Second, func() {
  302. // When pubsub is closed channel is closed too.
  303. _ = pubsub.Close()
  304. })
  305. // Consume messages.
  306. for msg := range ch {
  307. fmt.Println(msg.Channel, msg.Payload)
  308. }
  309. // Output: mychannel1 hello
  310. }
  311. func ExamplePubSub_Receive() {
  312. pubsub := redisdb.Subscribe("mychannel2")
  313. defer pubsub.Close()
  314. for i := 0; i < 2; i++ {
  315. // ReceiveTimeout is a low level API. Use ReceiveMessage instead.
  316. msgi, err := pubsub.ReceiveTimeout(time.Second)
  317. if err != nil {
  318. break
  319. }
  320. switch msg := msgi.(type) {
  321. case *redis.Subscription:
  322. fmt.Println("subscribed to", msg.Channel)
  323. _, err := redisdb.Publish("mychannel2", "hello").Result()
  324. if err != nil {
  325. panic(err)
  326. }
  327. case *redis.Message:
  328. fmt.Println("received", msg.Payload, "from", msg.Channel)
  329. default:
  330. panic("unreached")
  331. }
  332. }
  333. // sent message to 1 redisdb
  334. // received hello from mychannel2
  335. }
  336. func ExampleScript() {
  337. IncrByXX := redis.NewScript(`
  338. if redis.call("GET", KEYS[1]) ~= false then
  339. return redis.call("INCRBY", KEYS[1], ARGV[1])
  340. end
  341. return false
  342. `)
  343. n, err := IncrByXX.Run(redisdb, []string{"xx_counter"}, 2).Result()
  344. fmt.Println(n, err)
  345. err = redisdb.Set("xx_counter", "40", 0).Err()
  346. if err != nil {
  347. panic(err)
  348. }
  349. n, err = IncrByXX.Run(redisdb, []string{"xx_counter"}, 2).Result()
  350. fmt.Println(n, err)
  351. // Output: <nil> redis: nil
  352. // 42 <nil>
  353. }
  354. func Example_customCommand() {
  355. Get := func(redisdb *redis.Client, key string) *redis.StringCmd {
  356. cmd := redis.NewStringCmd("get", key)
  357. redisdb.Process(cmd)
  358. return cmd
  359. }
  360. v, err := Get(redisdb, "key_does_not_exist").Result()
  361. fmt.Printf("%q %s", v, err)
  362. // Output: "" redis: nil
  363. }
  364. func Example_customCommand2() {
  365. v, err := redisdb.Do("get", "key_does_not_exist").String()
  366. fmt.Printf("%q %s", v, err)
  367. // Output: "" redis: nil
  368. }
  369. func ExampleScanIterator() {
  370. iter := redisdb.Scan(0, "", 0).Iterator()
  371. for iter.Next() {
  372. fmt.Println(iter.Val())
  373. }
  374. if err := iter.Err(); err != nil {
  375. panic(err)
  376. }
  377. }
  378. func ExampleScanCmd_Iterator() {
  379. iter := redisdb.Scan(0, "", 0).Iterator()
  380. for iter.Next() {
  381. fmt.Println(iter.Val())
  382. }
  383. if err := iter.Err(); err != nil {
  384. panic(err)
  385. }
  386. }
  387. func ExampleNewUniversalClient_simple() {
  388. redisdb := redis.NewUniversalClient(&redis.UniversalOptions{
  389. Addrs: []string{":6379"},
  390. })
  391. defer redisdb.Close()
  392. redisdb.Ping()
  393. }
  394. func ExampleNewUniversalClient_failover() {
  395. redisdb := redis.NewUniversalClient(&redis.UniversalOptions{
  396. MasterName: "master",
  397. Addrs: []string{":26379"},
  398. })
  399. defer redisdb.Close()
  400. redisdb.Ping()
  401. }
  402. func ExampleNewUniversalClient_cluster() {
  403. redisdb := redis.NewUniversalClient(&redis.UniversalOptions{
  404. Addrs: []string{":7000", ":7001", ":7002", ":7003", ":7004", ":7005"},
  405. })
  406. defer redisdb.Close()
  407. redisdb.Ping()
  408. }