gredis_conn.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. // Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved.
  2. //
  3. // This Source Code Form is subject to the terms of the MIT License.
  4. // If a copy of the MIT was not distributed with this file,
  5. // You can obtain one at https://github.com/gogf/gf.
  6. package gredis
  7. import (
  8. "errors"
  9. "github.com/gogf/gf/container/gvar"
  10. "github.com/gogf/gf/internal/json"
  11. "github.com/gogf/gf/util/gconv"
  12. "github.com/gomodule/redigo/redis"
  13. "reflect"
  14. "time"
  15. )
  16. // Do sends a command to the server and returns the received reply.
  17. // It uses json.Marshal for struct/slice/map type values before committing them to redis.
  18. // The timeout overrides the read timeout set when dialing the connection.
  19. func (c *Conn) do(timeout time.Duration, commandName string, args ...interface{}) (reply interface{}, err error) {
  20. var (
  21. reflectValue reflect.Value
  22. reflectKind reflect.Kind
  23. )
  24. for k, v := range args {
  25. reflectValue = reflect.ValueOf(v)
  26. reflectKind = reflectValue.Kind()
  27. if reflectKind == reflect.Ptr {
  28. reflectValue = reflectValue.Elem()
  29. reflectKind = reflectValue.Kind()
  30. }
  31. switch reflectKind {
  32. case
  33. reflect.Struct,
  34. reflect.Map,
  35. reflect.Slice,
  36. reflect.Array:
  37. // Ignore slice type of: []byte.
  38. if _, ok := v.([]byte); !ok {
  39. if args[k], err = json.Marshal(v); err != nil {
  40. return nil, err
  41. }
  42. }
  43. }
  44. }
  45. if timeout > 0 {
  46. conn, ok := c.Conn.(redis.ConnWithTimeout)
  47. if !ok {
  48. return gvar.New(nil), errors.New(`current connection does not support "ConnWithTimeout"`)
  49. }
  50. return conn.DoWithTimeout(timeout, commandName, args...)
  51. }
  52. return c.Conn.Do(commandName, args...)
  53. }
  54. // Do sends a command to the server and returns the received reply.
  55. // It uses json.Marshal for struct/slice/map type values before committing them to redis.
  56. func (c *Conn) Do(commandName string, args ...interface{}) (reply interface{}, err error) {
  57. return c.do(0, commandName, args...)
  58. }
  59. // DoWithTimeout sends a command to the server and returns the received reply.
  60. // The timeout overrides the read timeout set when dialing the connection.
  61. func (c *Conn) DoWithTimeout(timeout time.Duration, commandName string, args ...interface{}) (reply interface{}, err error) {
  62. return c.do(timeout, commandName, args...)
  63. }
  64. // DoVar retrieves and returns the result from command as gvar.Var.
  65. func (c *Conn) DoVar(commandName string, args ...interface{}) (*gvar.Var, error) {
  66. return resultToVar(c.Do(commandName, args...))
  67. }
  68. // DoVarWithTimeout retrieves and returns the result from command as gvar.Var.
  69. // The timeout overrides the read timeout set when dialing the connection.
  70. func (c *Conn) DoVarWithTimeout(timeout time.Duration, commandName string, args ...interface{}) (*gvar.Var, error) {
  71. return resultToVar(c.DoWithTimeout(timeout, commandName, args...))
  72. }
  73. // ReceiveVar receives a single reply as gvar.Var from the Redis server.
  74. func (c *Conn) ReceiveVar() (*gvar.Var, error) {
  75. return resultToVar(c.Receive())
  76. }
  77. // ReceiveVarWithTimeout receives a single reply as gvar.Var from the Redis server.
  78. // The timeout overrides the read timeout set when dialing the connection.
  79. func (c *Conn) ReceiveVarWithTimeout(timeout time.Duration) (*gvar.Var, error) {
  80. conn, ok := c.Conn.(redis.ConnWithTimeout)
  81. if !ok {
  82. return gvar.New(nil), errors.New(`current connection does not support "ConnWithTimeout"`)
  83. }
  84. return resultToVar(conn.ReceiveWithTimeout(timeout))
  85. }
  86. // resultToVar converts redis operation result to gvar.Var.
  87. func resultToVar(result interface{}, err error) (*gvar.Var, error) {
  88. if err == nil {
  89. if result, ok := result.([]byte); ok {
  90. return gvar.New(gconv.UnsafeBytesToStr(result)), err
  91. }
  92. // It treats all returned slice as string slice.
  93. if result, ok := result.([]interface{}); ok {
  94. return gvar.New(gconv.Strings(result)), err
  95. }
  96. }
  97. return gvar.New(result), err
  98. }