- go-redis
- redigo
package main
import (
"fmt"
"github.com/garyburd/redigo/redis"
)
func main() {
c, err := redis.Dial("tcp", "localhost:6379")
if err != nil {
fmt.Println("Connect to redis error", err)
return
}
defer c.Close()
// 写入值永不过期
_, err = c.Do("SET", "username", "nick")
if err != nil {
fmt.Println("redis set failed:", err)
}
username, err := redis.String(c.Do("GET", "username"))
if err != nil {
fmt.Println("redis get failed:", err)
} else {
fmt.Printf("Got username %v \n", username)
}
SET命令还支持附加参数
EX seconds — 指定过期时间,单位为秒.
PX milliseconds — 指定过期时间,单位为毫秒.
NX — 仅当键值不存在时设置键值.
XX — 仅当键值存在时设置键值.
设置键值过期时间为10s
// 写入值10S后过期
_, err = c.Do("SET", "password", "123456", "EX", "10")
if err != nil {
fmt.Println("redis set failed:", err)
}
time.Sleep(11 * time.Second)
password, err := redis.String(c.Do("GET", "password"))
if err != nil {
fmt.Println("redis get failed:", err)
} else {
fmt.Printf("Got password %v \n", password)
}
输出
redis get failed: redigo: nil returned
批量写入读取
DEL key [key ...]
批量写入读取对象(Hashtable)
DEL key [key ...]
检测值是否存在
DEL key [key ...]
删除
DEL key [key ...]
设置过期时间
EXPIRE key seconds
分布式锁
Distributed mutual exclusion lock using Redis for Go
https://github.com/go-redsync/redsync
数据传输
package client
import (
"bufio"
"errors"
"fmt"
"net"
"strconv"
)
type Reply struct {
Conn *net.TCPConn
SingleReply []byte
MultiReply [][]byte
Source []byte
IsMulti bool
Err error
}
// 组成请求命令
func MultiCommandMarshal(args ...string) string {
var s string
s = "*"
s += strconv.Itoa(len(args))
s += "\r\n"
// 命令所有参数
for _, v := range args {
s += "$"
s += strconv.Itoa(len(v))
s += "\r\n"
s += v
s += "\r\n"
}
return s
}
// 预读取第一个字节判断是多行还是单行返回 分开处理
func (reply *Reply) Reply() {
rd := bufio.NewReader(reply.Conn)
b, err := rd.Peek(1)
if err != nil {
fmt.Println("conn error")
}
fmt.Println("prefix =", string(b))
if b[0] == byte('*') {
reply.IsMulti = true
reply.MultiReply, reply.Err = multiResponse(rd)
} else {
reply.IsMulti = false
reply.SingleReply, err = singleResponse(rd)
if err != nil {
reply.Err = err
return
}
}
}
// 多行返回 每次读取一行然后调用singleResponse 获取单行数据
func multiResponse(rd *bufio.Reader) ([][]byte, error) {
prefix, err := rd.ReadByte()
var result [][]byte
if err != nil {
return result, err
}
if prefix != byte('*') {
return result, errors.New("not multi response")
}
//*3\r\n$1\r\n3\r\n$1\r\n2\r\n$1\r\n
l, _, err := rd.ReadLine()
if err != nil {
return result, err
}
n, err := strconv.Atoi(string(l))
if err != nil {
return result, err
}
for i := 0; i < n; i++ {
s, err := singleResponse(rd)
fmt.Println("i =", i, "result = ", string(s))
if err != nil {
return result, err
}
result = append(result, s)
}
return result, nil
}
// 获取单行数据 + - : 逻辑相同 $单独处理
func singleResponse(rd *bufio.Reader) ([]byte, error) {
var (
result []byte
err error
)
prefix, err := rd.ReadByte()
if err != nil {
return []byte{}, err
}
switch prefix {
case byte('+'), byte('-'), byte(':'):
result, _, err = rd.ReadLine()
case byte('$'):
// $7\r\nliangwt\r\n
n, _, err := rd.ReadLine()
if err != nil {
return []byte{}, err
}
l, err := strconv.Atoi(string(n))
if err != nil {
return []byte{}, err
}
p := make([]byte, l+2)
rd.Read(p)
result = p[0 : len(p)-2]
}
return result, err
}
测试
package main
import (
"bufio"
"flag"
"fmt"
"log"
"net"
"os"
"strconv"
"strings"
"test/redis/rediscli/client"
)
var host string
var port string
func init() {
// 参数获取 设置有默认值
flag.StringVar(&host, "h", "localhost", "hsot")
flag.StringVar(&port, "p", "6379", "port")
}
func main() {
flag.Parse()
porti, err := strconv.Atoi(port)
if err != nil {
panic("port is error")
}
tcpAddr := &net.TCPAddr{IP: net.ParseIP(host), Port: porti}
conn, err := net.DialTCP("tcp", nil, tcpAddr)
if err != nil {
log.Println(err)
}
defer conn.Close()
for {
fmt.Printf("%s:%d>", host, porti)
bio := bufio.NewReader(os.Stdin)
input, _, err := bio.ReadLine()
if err != nil {
fmt.Println(err)
}
s := strings.Split(string(input), " ")
req := client.MultiCommandMarshal(s...)
conn.Write([]byte(req))
reply := client.Reply{}
reply.Conn = conn
reply.Reply()
if reply.Err != nil {
fmt.Println("err:", reply.Err)
}
var res []byte
if reply.IsMulti {
} else {
res = reply.SingleReply
}
fmt.Println("result:", string(res), "\nerr:", err)
//fmt.Println(string(p))
}
}
参考
https://github.com/gomodule/redigo
https://segmentfault.com/a/1190000019310103