1. package main
  2. import (
  3. "fmt"
  4. "github.com/garyburd/redigo/redis"
  5. )
  6. func main() {
  7. c, err := redis.Dial("tcp", "localhost:6379")
  8. if err != nil {
  9. fmt.Println("Connect to redis error", err)
  10. return
  11. }
  12. defer c.Close()
  1. // 写入值永不过期
  2. _, err = c.Do("SET", "username", "nick")
  3. if err != nil {
  4. fmt.Println("redis set failed:", err)
  5. }
  6. username, err := redis.String(c.Do("GET", "username"))
  7. if err != nil {
  8. fmt.Println("redis get failed:", err)
  9. } else {
  10. fmt.Printf("Got username %v \n", username)
  11. }

SET命令还支持附加参数

EX seconds — 指定过期时间,单位为秒.
PX milliseconds — 指定过期时间,单位为毫秒.
NX — 仅当键值不存在时设置键值.
XX — 仅当键值存在时设置键值.
设置键值过期时间为10s
// 写入值10S后过期

  1. _, err = c.Do("SET", "password", "123456", "EX", "10")
  2. if err != nil {
  3. fmt.Println("redis set failed:", err)
  4. }
  5. time.Sleep(11 * time.Second)
  6. password, err := redis.String(c.Do("GET", "password"))
  7. if err != nil {
  8. fmt.Println("redis get failed:", err)
  9. } else {
  10. fmt.Printf("Got password %v \n", password)
  11. }

输出
redis get failed: redigo: nil returned
批量写入读取

  1. DEL key [key ...]

批量写入读取对象(Hashtable)

  1. DEL key [key ...]

检测值是否存在

  1. DEL key [key ...]

删除

  1. DEL key [key ...]

设置过期时间

  1. EXPIRE key seconds

分布式锁

Distributed mutual exclusion lock using Redis for Go
https://github.com/go-redsync/redsync

数据传输

  1. package client
  2. import (
  3. "bufio"
  4. "errors"
  5. "fmt"
  6. "net"
  7. "strconv"
  8. )
  9. type Reply struct {
  10. Conn *net.TCPConn
  11. SingleReply []byte
  12. MultiReply [][]byte
  13. Source []byte
  14. IsMulti bool
  15. Err error
  16. }
  17. // 组成请求命令
  18. func MultiCommandMarshal(args ...string) string {
  19. var s string
  20. s = "*"
  21. s += strconv.Itoa(len(args))
  22. s += "\r\n"
  23. // 命令所有参数
  24. for _, v := range args {
  25. s += "$"
  26. s += strconv.Itoa(len(v))
  27. s += "\r\n"
  28. s += v
  29. s += "\r\n"
  30. }
  31. return s
  32. }
  33. // 预读取第一个字节判断是多行还是单行返回 分开处理
  34. func (reply *Reply) Reply() {
  35. rd := bufio.NewReader(reply.Conn)
  36. b, err := rd.Peek(1)
  37. if err != nil {
  38. fmt.Println("conn error")
  39. }
  40. fmt.Println("prefix =", string(b))
  41. if b[0] == byte('*') {
  42. reply.IsMulti = true
  43. reply.MultiReply, reply.Err = multiResponse(rd)
  44. } else {
  45. reply.IsMulti = false
  46. reply.SingleReply, err = singleResponse(rd)
  47. if err != nil {
  48. reply.Err = err
  49. return
  50. }
  51. }
  52. }
  53. // 多行返回 每次读取一行然后调用singleResponse 获取单行数据
  54. func multiResponse(rd *bufio.Reader) ([][]byte, error) {
  55. prefix, err := rd.ReadByte()
  56. var result [][]byte
  57. if err != nil {
  58. return result, err
  59. }
  60. if prefix != byte('*') {
  61. return result, errors.New("not multi response")
  62. }
  63. //*3\r\n$1\r\n3\r\n$1\r\n2\r\n$1\r\n
  64. l, _, err := rd.ReadLine()
  65. if err != nil {
  66. return result, err
  67. }
  68. n, err := strconv.Atoi(string(l))
  69. if err != nil {
  70. return result, err
  71. }
  72. for i := 0; i < n; i++ {
  73. s, err := singleResponse(rd)
  74. fmt.Println("i =", i, "result = ", string(s))
  75. if err != nil {
  76. return result, err
  77. }
  78. result = append(result, s)
  79. }
  80. return result, nil
  81. }
  82. // 获取单行数据 + - : 逻辑相同 $单独处理
  83. func singleResponse(rd *bufio.Reader) ([]byte, error) {
  84. var (
  85. result []byte
  86. err error
  87. )
  88. prefix, err := rd.ReadByte()
  89. if err != nil {
  90. return []byte{}, err
  91. }
  92. switch prefix {
  93. case byte('+'), byte('-'), byte(':'):
  94. result, _, err = rd.ReadLine()
  95. case byte('$'):
  96. // $7\r\nliangwt\r\n
  97. n, _, err := rd.ReadLine()
  98. if err != nil {
  99. return []byte{}, err
  100. }
  101. l, err := strconv.Atoi(string(n))
  102. if err != nil {
  103. return []byte{}, err
  104. }
  105. p := make([]byte, l+2)
  106. rd.Read(p)
  107. result = p[0 : len(p)-2]
  108. }
  109. return result, err
  110. }

测试

  1. package main
  2. import (
  3. "bufio"
  4. "flag"
  5. "fmt"
  6. "log"
  7. "net"
  8. "os"
  9. "strconv"
  10. "strings"
  11. "test/redis/rediscli/client"
  12. )
  13. var host string
  14. var port string
  15. func init() {
  16. // 参数获取 设置有默认值
  17. flag.StringVar(&host, "h", "localhost", "hsot")
  18. flag.StringVar(&port, "p", "6379", "port")
  19. }
  20. func main() {
  21. flag.Parse()
  22. porti, err := strconv.Atoi(port)
  23. if err != nil {
  24. panic("port is error")
  25. }
  26. tcpAddr := &net.TCPAddr{IP: net.ParseIP(host), Port: porti}
  27. conn, err := net.DialTCP("tcp", nil, tcpAddr)
  28. if err != nil {
  29. log.Println(err)
  30. }
  31. defer conn.Close()
  32. for {
  33. fmt.Printf("%s:%d>", host, porti)
  34. bio := bufio.NewReader(os.Stdin)
  35. input, _, err := bio.ReadLine()
  36. if err != nil {
  37. fmt.Println(err)
  38. }
  39. s := strings.Split(string(input), " ")
  40. req := client.MultiCommandMarshal(s...)
  41. conn.Write([]byte(req))
  42. reply := client.Reply{}
  43. reply.Conn = conn
  44. reply.Reply()
  45. if reply.Err != nil {
  46. fmt.Println("err:", reply.Err)
  47. }
  48. var res []byte
  49. if reply.IsMulti {
  50. } else {
  51. res = reply.SingleReply
  52. }
  53. fmt.Println("result:", string(res), "\nerr:", err)
  54. //fmt.Println(string(p))
  55. }
  56. }

参考

https://github.com/gomodule/redigo
https://segmentfault.com/a/1190000019310103