-
Notifications
You must be signed in to change notification settings - Fork 71
/
redis.go
133 lines (113 loc) · 3.41 KB
/
redis.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package redis
import (
"github.com/go-redis/redis"
"github.com/philippgille/gokv/encoding"
"github.com/philippgille/gokv/util"
)
// Client is a gokv.Store implementation for Redis.
type Client struct {
c *redis.Client
codec encoding.Codec
}
// Set stores the given value for the given key.
// Values are automatically marshalled to JSON or gob (depending on the configuration).
// The key must not be "" and the value must not be nil.
func (c Client) Set(k string, v interface{}) error {
if err := util.CheckKeyAndValue(k, v); err != nil {
return err
}
// First turn the passed object into something that Redis can handle
// (the Set method takes an interface{}, but the Get method only returns a string,
// so it can be assumed that the interface{} parameter type is only for convenience
// for a couple of builtin types like int etc.).
data, err := c.codec.Marshal(v)
if err != nil {
return err
}
err = c.c.Set(k, string(data), 0).Err()
if err != nil {
return err
}
return nil
}
// Get retrieves the stored value for the given key.
// You need to pass a pointer to the value, so in case of a struct
// the automatic unmarshalling can populate the fields of the object
// that v points to with the values of the retrieved object's values.
// If no value is found it returns (false, nil).
// The key must not be "" and the pointer must not be nil.
func (c Client) Get(k string, v interface{}) (found bool, err error) {
if err := util.CheckKeyAndValue(k, v); err != nil {
return false, err
}
dataString, err := c.c.Get(k).Result()
if err != nil {
if err == redis.Nil {
return false, nil
}
return false, err
}
return true, c.codec.Unmarshal([]byte(dataString), v)
}
// Delete deletes the stored value for the given key.
// Deleting a non-existing key-value pair does NOT lead to an error.
// The key must not be "".
func (c Client) Delete(k string) error {
if err := util.CheckKey(k); err != nil {
return err
}
_, err := c.c.Del(k).Result()
return err
}
// Close closes the client.
// It must be called to release any open resources.
func (c Client) Close() error {
return c.c.Close()
}
// Options are the options for the Redis client.
type Options struct {
// Address of the Redis server, including the port.
// Optional ("localhost:6379" by default).
Address string
// Password for the Redis server.
// Optional ("" by default).
Password string
// DB to use.
// Optional (0 by default).
DB int
// Encoding format.
// Optional (encoding.JSON by default).
Codec encoding.Codec
}
// DefaultOptions is an Options object with default values.
// Address: "localhost:6379", Password: "", DB: 0, Codec: encoding.JSON
var DefaultOptions = Options{
Address: "localhost:6379",
Codec: encoding.JSON,
// No need to set Password or DB because their Go zero values are fine for that.
}
// NewClient creates a new Redis client.
//
// You must call the Close() method on the client when you're done working with it.
func NewClient(options Options) (Client, error) {
result := Client{}
// Set default values
if options.Address == "" {
options.Address = DefaultOptions.Address
}
if options.Codec == nil {
options.Codec = DefaultOptions.Codec
}
client := redis.NewClient(&redis.Options{
Addr: options.Address,
Password: options.Password,
DB: options.DB,
})
err := client.Ping().Err()
if err != nil {
return result, err
}
result.c = client
result.codec = options.Codec
return result, nil
}