go get -u github.com/go-redis/redis
// 声明一个全局的rdb变量
var rdb *redis.Client
// 初始化连接
func initClient() (err error) {
rdb = redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
})
_, err = rdb.Ping().Result()
if err != nil {
return err
}
return nil
}
2.redid.Z结构体
type Z struct {
Score float64
Member interface{}
}
3.cmdable接口
3.1接口
//这个接口有很多方法
type Cmdable interface {
Pipeline() Pipeliner
Pipelined(fn func(Pipeliner) error) ([]Cmder, error)
TxPipelined(fn func(Pipeliner) error) ([]Cmder, error)
TxPipeline() Pipeliner
Command() *CommandsInfoCmd
ClientGetName() *StringCmd
Echo(message interface{}) *StringCmd
Ping() *StatusCmd
.............
}
3.2ZAdd方法
func (c *cmdable) ZAdd(key string, members ...Z) *IntCmd {}
3.3ZIncrBy方法
func (c *cmdable) ZIncrBy(key string, increment float64, member string) *FloatCmd {}
3.4ZRevRangeWithScores方法
func (c *cmdable) ZRevRangeWithScores(key string, start, stop int64) *ZSliceCmd {}
3.5ZRangeByScoreWithScores方法
func (c *cmdable) ZRangeByScoreWithScores(key string, opt ZRangeBy) *ZSliceCmd {
3.6Incr方法
func (c *cmdable) Incr(key string) *IntCmd {}
4.redsi.Pipeliner接口
type Pipeliner interface {
StatefulCmdable
Do(args ...interface{}) *Cmd
Process(cmd Cmder) error
Close() error
Discard() error
Exec() ([]Cmder, error)
}
5.redis.Client结构体
5.1结构体
type Client struct {
baseClient
cmdable
ctx context.Context
}
5.2TxPipeline方法
func (c *Client) TxPipeline() Pipeliner {}
6.redis.baseClient结构体
6.1结构体
type baseClient struct {
opt *Options
connPool pool.Pooler
limiter Limiter
process func(Cmder) error
processPipeline func([]Cmder) error
processTxPipeline func([]Cmder) error
onClose func() error // hook called when client is closed
}
6.2Do方法
func (c *baseClient) Do(args ...interface{}) *Cmd {
7.redis.IntCmd结构体
7.1结构体
type IntCmd struct {
baseCmd
val int64
}
7.2Result方法
func (cmd *IntCmd) Result() (int64, error) {
return cmd.val, cmd.err
}
8.redis.FloatCmd结构体
8.1结构体
type FloatCmd struct {
baseCmd
val float64
}
8.2Result方法
func (cmd *FloatCmd) Result() (float64, error) {
return cmd.Val(), cmd.Err()
}
9.redis.ZSliceCmd结构体
9.1结构体
type ZSliceCmd struct {
baseCmd
val []Z
}
9.2Result方法
func (cmd *ZSliceCmd) Result() ([]Z, error) {
return cmd.val, cmd.err
}
10.baseCmd结构体
type baseCmd struct {
_args []interface{}
err error
_readTimeout *time.Duration
}
11.redis.ZRangeBy结构体
type ZRangeBy struct {
Min, Max string
Offset, Count int64
}
12.sortedset有序集合zadd *** 作
package main
import (
"fmt"
"github.com/go-redis/redis"
)
// 声明一个全局的rdb变量
var rdb *redis.Client
// 初始化连接
func initClient() (err error) {
rdb = redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
})
//Ping返回的是:*StatusCmd ; Result方法是StatusCmd结构体的方法(StatusCmd的val, baseCmd的err)
_, err = rdb.Ping().Result()
if err != nil {
return err
}
return nil
}
func redisExample2() {
if err := initClient(); err != nil {
return
}
zsetKey := "language_rank"
languages := []redis.Z{
redis.Z{Score: 90.0, Member: "Golang"},
redis.Z{Score: 98.0, Member: "Java"},
redis.Z{Score: 95.0, Member: "Python"},
redis.Z{Score: 97.0, Member: "JavaScript"},
redis.Z{Score: 99.0, Member: "C/C++"},
}
// ZADD
num, err := rdb.ZAdd(zsetKey, languages...).Result()
if err != nil {
fmt.Printf("zadd failed, err:%v\n", err)
return
}
fmt.Printf("zadd %d succ.\n", num)//输出:zadd 5 succ.
// 把Golang的分数加10
newScore, err := rdb.ZIncrBy(zsetKey, 10.0, "Golang").Result()
if err != nil {
fmt.Printf("zincrby failed, err:%v\n", err)
return
}
fmt.Printf("Golang's score is %f now.\n", newScore)//输出:Golang's score is 100.000000 now.
// 取分数最高的3个;
ret, err := rdb.ZRevRangeWithScores(zsetKey, 0, 2).Result()
if err != nil {
fmt.Printf("zrevrange failed, err:%v\n", err)
/*输出:Golang 100
C/C++ 99
Java 98*/
return
}
for _, z := range ret {
fmt.Println(z.Member, z.Score)
}
// 取95~100分的
op := redis.ZRangeBy{
Min: "95",
Max: "100",
}
ret, err = rdb.ZRangeByScoreWithScores(zsetKey, op).Result()
if err != nil {
fmt.Printf("zrangebyscore failed, err:%v\n", err)
return
}
for _, z := range ret {
fmt.Println(z.Member, z.Score)
/*输出:
Python 95
JavaScript 97
Java 98
C/C++ 99
Golang 100*/
}
}
func main() {
redisExample2()
/*输出:
zadd 5 succ.
Golang's score is 100.000000 now.
Golang 100
C/C++ 99
Java 98
Python 95
JavaScript 97
Java 98
C/C++ 99
Golang 100
*/
}
13.事务示例1
Redis是单线程的,因此单个命令始终是原子的,但是来自不同客户端的两个给定命令可以依次执行,例如在它们之间交替执行。但是,Multi/exec能够确保在multi/exec两个语句之间的命令之间没有其他客户端正在执行命令。
在这种场景我们需要使用TxPipeline。TxPipeline总体上类似于上面的Pipeline,但是它内部会使用MULTI/EXEC包裹排队的命令
package main
import (
"fmt"
"github.com/go-redis/redis"
)
// 声明一个全局的rdb变量
var rdb *redis.Client
// 初始化连接
func initClient() (err error) {
rdb = redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
})
_, err = rdb.Ping().Result()
if err != nil {
return err
}
return nil
}
func V8Example() {
initClient()
//Do是baseClient结构体的方法
rdb.Do("set", "key8", "value8")
//Client结构体里面有cmdable结构体
//Keys是cmable结构体的方法,返回*StringSliceCmd
// Result是StringSliceCmd结构体的方法
vals, _ := rdb.Keys("k*").Result()
fmt.Println(vals) //输出:[key8]
//返回的是Pipeliner接口
pipe := rdb.TxPipeline() //相当于MULTI开启事务
//Pipeliner接口里定义有Do这个方法
pipe.Do("set", "key8", "value8")
pipe.Do("set", "key9", "value9")
vals1, _ := rdb.Keys("k*").Result()
fmt.Println(vals1) //输出:[key8]
vals2, _ := pipe.Keys("k*").Result()
fmt.Println(vals2) //输出:[]
//Pipeliner接口里定义有Exec这个方法
pipe.Exec() ///相当于EXEC事务
vals3, _ := rdb.Keys("k*").Result()
fmt.Println(vals3) //输出[key8 key9]
}
func main() {
V8Example()
}
14.事务示例2
package main
import (
"fmt"
"github.com/go-redis/redis"
"time"
)
// 声明一个全局的rdb变量
var rdb *redis.Client
// 初始化连接
func initClient() (err error) {
rdb = redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
})
_, err = rdb.Ping().Result()
if err != nil {
return err
}
return nil
}
func V8Example() {
initClient()
rdb.Do("set", "tx_pipeline_counter", "1")
val, _ := rdb.Get("tx_pipeline_counter").Result()
fmt.Println(val) //输出:1
pipe := rdb.TxPipeline()
incr := pipe.Incr("tx_pipeline_counter")
pipe.Expire("tx_pipeline_counter", time.Hour)
pipe.Exec()
fmt.Println(incr.Val())//输出:2
val1, _ := rdb.Get("tx_pipeline_counter").Result()
fmt.Println(val1) //输出:2
}
func main() {
V8Example()
}
二、go-redis/redis(v8)
1.redis依赖安装
最新版本的go-redis库的相关命令都需要传递context.Context参数,例如:
2.redis.NewClient函数
func NewClient(opt *Options) *Client {}
//Options是一个结构体,里面有很多参数
3.redis.Client结构体
3.1结构体
type Client struct {
*baseClient
cmdable
hooks
ctx context.Context
}
3.2Do方法
func (c *Client) Do(ctx context.Context, args ...interface{}) *Cmd {}
3.3TxPipeline方法
func (c *Client) TxPipeline() Pipeliner {}
4.redis.Pipeliner接口
type Pipeliner interface {
StatefulCmdable
Do(ctx context.Context, args ...interface{}) *Cmd
Process(ctx context.Context, cmd Cmder) error
Close() error
Discard() error
Exec(ctx context.Context) ([]Cmder, error)
}
5.redis.Cmd结构体
type Cmd struct {
baseCmd
val interface{}
}
6.baseCmd结构体
6.1结构体
//注意:引用不到,因为是小写
type baseCmd struct {
ctx context.Context
args []interface{}
err error
keyPos int8
_readTimeout *time.Duration
}
6.2Err()方法
func (cmd *baseCmd) Err() error {
return cmd.err
}
7.redis.StringCmd结构体
7.1结构体
type StringCmd struct {
baseCmd
val string
}
7.2Val方法
func (cmd *StringCmd) Val() string {
return cmd.val
}
7.3Result方法
func (cmd *StringCmd) Result() (string, error) {
return cmd.Val(), cmd.err
}
8.redis.StatusCmd结构体
8.1结构体
type StatusCmd struct {
baseCmd
val string
}
8.2Result方法
func (cmd *StatusCmd) Result() (string, error) {
return cmd.val, cmd.err
}
9.redis.StringSliceCmd结构体
9.1结构体
type StringSliceCmd struct {
baseCmd
val []string
}
9.2Result()方法
func (cmd *StringSliceCmd) Result() ([]string, error) {
return cmd.Val(), cmd.Err()
}
10.redis.ScanCmd结构体
11.1结构体
type ScanCmd struct {
baseCmd
page []string
cursor uint64
process cmdable
}
11.2Iterator方法
func (cmd *ScanCmd) Iterator() *ScanIterator {
return &ScanIterator{
cmd: cmd,
}
}
12.redis.ScanIterator结构体
12.1结构体
type ScanIterator struct {
mu sync.Mutex // protects Scanner and pos
cmd *ScanCmd
pos int
}
12.2Next方法
func (it *ScanIterator) Next(ctx context.Context) bool {}
13.redis.IntCmd结构体
13.1结构体
type IntCmd struct {
baseCmd
val int64
}
14.cmdable类型
14.1类型
type cmdable func(ctx context.Context, cmd Cmder) error
14.2Set方法
func (c cmdable) Set(ctx context.Context, key string, value interface{}, expiration time.Duration) *StatusCmd {}
14.3Get方法
func (c cmdable) Get(ctx context.Context, key string) *StringCmd {}
14.4Ping方法
func (c cmdable) Ping(ctx context.Context) *StatusCmd {}
14.5Keys方法
func (c cmdable) Keys(ctx context.Context, pattern string) *StringSliceCmd {}
14.6Scan方法
func (c cmdable) Scan(ctx context.Context, cursor uint64, match string, count int64) *ScanCmd {}
14.7Del方法
func (c cmdable) Del(ctx context.Context, keys ...string) *IntCmd {}
15.NewClusterClient函数
func NewClusterClient(opt *ClusterOptions) *ClusterClient {}
16.NewFailoverClient函数
func NewFailoverClient(failoverOpt *FailoverOptions) *Client {}
17.String类型Set、Get单 *** 作
package main
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
"time"
)
var (
rdb *redis.Client
)
// 初始化连接
func initClient() (err error) {
rdb = redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
PoolSize: 100, // 连接池大小
})
/*func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
return WithDeadline(parent, time.Now().Add(timeout))}*/
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
//Ping返回的是:*StatusCmd ; Result方法是StatusCmd结构体的方法(StatusCmd的val, baseCmd的err)
_, err = rdb.Ping(ctx).Result()
return err
}
func V8Example() {
/*func Background() Context {
return background
}
*/
ctx := context.Background()
if err := initClient(); err != nil {
//Set是cmdable的方法Set返回的是*StatusCmd;StatusCmd结构体里面有basecmd
//Err()是baseCmd结构体的方法 (baseCmd.err)
//rdb是client结构体,这个结构体里面有cmdable类型,
err := rdb.Set(ctx, "key", "value", 0).Err()
if err != nil {
panic(err)
}
//Set返回的是*StringCmd; Result是StringCmd结构体的方法 (StringCmd.Val() [StringCmd.val] )
val, err := rdb.Get(ctx, "key").Result()
if err != nil {
panic(err)
}
fmt.Println("key", val)
val2, err := rdb.Get(ctx, "key2").Result()
if err == redis.Nil {
fmt.Println("key2 does not exist")
} else if err != nil {
panic(err)
} else {
fmt.Println("key2", val2)
}
// Output: key value
// key2 does not exist
}
}
func main() {
V8Example()
/*输出:
key value
key2 does not exist
*/
}
18.根据前缀获取Key
package main
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
"time"
)
var (
rdb *redis.Client
)
// 初始化连接
func initClient() (err error) {
rdb = redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
PoolSize: 100, // 连接池大小
})
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_, err = rdb.Ping(ctx).Result()
return err
}
func V8Example() {
ctx := context.Background()
err := initClient()
rdb.Set(ctx, "key", "value", 0).Err()
rdb.Set(ctx, "keppp", "value", 0).Err()
vals, _ := rdb.Keys(ctx, "k*").Result()
if err != nil {
panic(err)
}
fmt.Println(vals) //输出: [key keppp]
}
func main() {
V8Example()
}
19.执行自定义命令
package main
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
"time"
)
var (
rdb *redis.Client
)
// 初始化连接
func initClient() (err error) {
rdb = redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
PoolSize: 100, // 连接池大小
})
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_, err = rdb.Ping(ctx).Result()
return err
}
func V8Example() {
ctx := context.Background()
initClient()
//Do是Client结构体的方法
rdb.Do(ctx, "set", "key1", "value1").Result()
val1, _ := rdb.Get(ctx, "key1").Result()
val2, _ := rdb.Do(ctx, "get", "key1").Result()
fmt.Println(val1) //输出:val1
fmt.Println(val2) //输出:val1
}
func main() {
V8Example()
}
20.按通配符删除key
当通配符匹配的key的数量不多时,可以使用Keys()得到所有的key在使用Del命令删除。 如果key的数量非常多的时候,我们可以搭配使用Scan命令和Del命令完成删除。
package main
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
"time"
)
var (
rdb *redis.Client
)
// 初始化连接
func initClient() (err error) {
rdb = redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
PoolSize: 100, // 连接池大小
})
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_, err = rdb.Ping(ctx).Result()
return err
}
func V8Example() {
initClient()
ctx := context.Background()
rdb.Do(ctx, "set", "key1", "value1").Result()
rdb.Do(ctx, "set", "key2", "value2").Result()
vals1, _ := rdb.Keys(ctx, "k*").Result()
fmt.Println(vals1) //输出:[key2 key1]
iter := rdb.Scan(ctx, 0, "k*", 0).Iterator()
for iter.Next(ctx) {
err := rdb.Del(ctx, iter.Val()).Err()
if err != nil {
panic(err)
}
}
vals2, _ := rdb.Keys(ctx, "k*").Result()
fmt.Println(vals2)//输出:[]
}
func main() {
V8Example()
}
21.连接redis集群
func initClient() (err error) {
rdb := redis.NewClusterClient(&redis.ClusterOptions{
Addrs: []string{":7000", ":7001", ":7002", ":7003", ":7004", ":7005"},
})
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
//Ping返回的是:*StatusCmd ; Result方法是StatusCmd结构体的方法(StatusCmd的val, baseCmd的err)
_, err = rdb.Ping(ctx).Result()
return err
}
22.连接Redis哨兵模式
func initClient() (err error) {
rdb := redis.NewFailoverClient(&redis.FailoverOptions{
MasterName: "master",
SentinelAddrs: []string{"x.x.x.x:26379", "xx.xx.xx.xx:26379", "xxx.xxx.xxx.xxx:26379"},
})
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_, err = rdb.Ping(ctx).Result()
return err
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)