跟我一起来学golang之《操作redis》(一)

1,571 阅读7分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

我们平时开发会经常用到redis。redis的应用场景有很多,在这就不介绍了,也不是本文的重点,接下来带大家了解一下如何用golang操作redis。

1.安装依赖包

go get -u github.com/go-redis/redis

2.golang连接redis

// 根据redis配置初始化一个客户端
client := redis.NewClient(&redis.Options{
		Addr:     "localhost:6379", // redis地址
		Password: "", // redis密码,没有则留空
		DB:       0,  // 默认数据库,默认是0
	})

3.简单的例子

  // 根据redis配置初始化一个客户端
	client := redis.NewClient(&redis.Options{
		Addr:     "10.14.181.120:6379", // redis地址
		Password: "", // redis密码,没有则留空
		DB:       0,  // 默认数据库,默认是0
		PoolSize: 10,
	})

	//ping := client.Ping()
	//fmt.Println(ping)

	// 设置一个key,过期时间为0,意思就是永远不过期
	for i := 0; i < 100; i++ {
		err := client.Set("key"+strconv.Itoa(i), "value"+strconv.Itoa(i), time.Hour*1).Err()

		// 检测设置是否成功
		if err != nil {
			panic(err)
		}
	}
	// 根据key查询缓存,通过Result函数返回两个值
	//  第一个代表key的值,第二个代表查询错误信息
	val := client.Get("key").Val()
	if val == "" {

		fmt.Println("取值是null")
	}
	fmt.Println("key", val)

	keys := client.Keys("*")

	for e,v := range keys.Val() {
		fmt.Println("------",e,v)
		//client.Del(v)
	}

接下来我们具体详细的讲解一下相关参数:

通过例子,我们知道主要通过Options配置redis的连接参数,下面对Options参数进行详细说明。

提示:go-redis包自带了连接池,会自动维护redis连接,因此创建一次client即可,不要查询一次redis就关闭client。

4.Options参数详解

type Options struct {
	// 网络类型 tcp 或者 unix.
	// 默认是 tcp.
	Network string
	// redis地址,格式 host:port
	Addr string

	// 新建一个redis连接的时候,会回调这个函数
	OnConnect func(*Conn) error

	// redis密码,redis server没有设置可以为空。
	Password string
	
	// redis数据库,序号从0开始,默认是0,可以不用设置
	DB int

	// redis操作失败最大重试次数,默认不重试。
	MaxRetries int
	
	// 最小重试时间间隔.
	// 默认是 8ms ; -1 表示关闭.
	MinRetryBackoff time.Duration
	
	// 最大重试时间间隔
	// 默认是 512ms; -1 表示关闭.
	MaxRetryBackoff time.Duration

	// redis连接超时时间.
	// 默认是 5 秒.
	DialTimeout time.Duration
	
	// socket读取超时时间
	// 默认 3 秒.
	ReadTimeout time.Duration
	
	// socket写超时时间
	WriteTimeout time.Duration

	// redis连接池的最大连接数.
	// 默认连接池大小等于 cpu个数 * 10
	PoolSize int
	
	// redis连接池最小空闲连接数.
	MinIdleConns int
	// redis连接最大的存活时间,默认不会关闭过时的连接.
	MaxConnAge time.Duration
	
	// 当你从redis连接池获取一个连接之后,连接池最多等待这个拿出去的连接多长时间。
	// 默认是等待 ReadTimeout + 1 秒.
	PoolTimeout time.Duration
	// redis连接池多久会关闭一个空闲连接.
	// 默认是 5 分钟. -1 则表示关闭这个配置项
	IdleTimeout time.Duration
	// 多长时间检测一下,空闲连接
	// 默认是 1 分钟. -1 表示关闭空闲连接检测
	IdleCheckFrequency time.Duration

	// 只读设置,如果设置为true, redis只能查询缓存不能更新。
	readOnly bool
}

5.基本操作

redis基本的key/value操作,指的是针对value值的类型为字符串或者数字类型的读写操作。

golang redis常用函数列表:

  • Set - 设置一个key的值
  • Get - 查询key的值
  • GetSet - 设置一个key的值,并返回这个key的旧值
  • SetNX - 如果key不存在,则设置这个key的值
  • MGet - 批量查询key的值
  • MSet - 批量设置key的值
  • Incr,IncrBy,IncrByFloat - 针对一个key的数值进行递增操作
  • Decr,DecrBy - 针对一个key的数值进行递减操作
  • Del - 删除key操作,可以批量删除
  • Expire - 设置key的过期时间

1.Set

设置一个key的值

// 第三个参数代表key的过期时间,0代表不会过期。
err := client.Set("key", "value", 0).Err()
if err != nil {
	panic(err)
}

2.Get

查询key的值

// Result函数返回两个值,第一个是key的值,第二个是错误信息
val, err := client.Get("key").Result()
// 判断查询是否出错
if err != nil {
	panic(err)
}
fmt.Println("key", val)

3.GetSet

设置一个key的值,并返回这个key的旧值

// Result函数返回两个值,第一个是key的值,第二个是错误信息
oldVal, err := client.GetSet("key", "new value").Result()

if err != nil {
	panic(err)
}
// 打印key的旧值
fmt.Println("key", oldVal)

4.SetNX

如果key不存在,则设置这个key的值

// 第三个参数代表key的过期时间,0代表不会过期。
err := client.SetNX("key", "value", 0).Err()
if err != nil {
	panic(err)
}

5.MGet

批量查询key的值

// MGet函数可以传入任意个key,一次性返回多个值。
// 这里Result返回两个值,第一个值是一个数组,第二个值是错误信息
vals, err := client.MGet("key1", "key2", "key3").Result()
if err != nil {
	panic(err)
}
fmt.Println(vals)

6.MSet

批量设置key的值

err := client.MSet("key1", "value1", "key2", "value2", "key3", "value3").Err()
if err != nil {
  panic(err)
}

7.Incr,IncrBy

针对一个key的数值进行递增操作

// Incr函数每次加一
val, err := client.Incr("key").Result()
if err != nil {
	panic(err)
}
fmt.Println("最新值", val)

// IncrBy函数,可以指定每次递增多少
val, err := client.IncrBy("key", 2).Result()
if err != nil {
	panic(err)
}
fmt.Println("最新值", val)

// IncrByFloat函数,可以指定每次递增多少,跟IncrBy的区别是累加的是浮点数
val, err := client.IncrByFloat("key", 2).Result()
if err != nil {
	panic(err)
}
fmt.Println("最新值", val)

8.Decr,DecrBy

针对一个key的数值进行递减操作

// Decr函数每次减一
val, err := client.Decr("key").Result()
if err != nil {
	panic(err)
}
fmt.Println("最新值", val)

// DecrBy函数,可以指定每次递减多少
val, err := client.DecrBy("key", 2).Result()
if err != nil {
	panic(err)
}
fmt.Println("最新值", val)

9.Del

删除key操作,支持批量删除

// 删除key
client.Del("key")

// 删除多个key, Del函数支持删除多个key
err := client.Del("key1", "key2", "key3").Err()
if err != nil {
	panic(err)
}

10.Expire

设置key的过期时间,单位秒

client.Expire("key", 3)

6.hash相关

如果你希望key/value的值也能作为hash结构进行操作,可以选择redis hash类型。

使用场景举例: 如果我们希望缓存一条用户信息(包括用户id、用户名、email字段),希望能够做到局部读写用户信息(例如:读写用户名),也能够读取整条用户信息,那么hash类型就支持这些操作。

redis hash操作主要有2-3个元素组成:

  • key - redis key 唯一标识
  • field - hash数据的字段名
  • value - 值,有些操作不需要值

go redis hash数据常用函数:

  • HSet - 根据key和field字段设置,field字段的值
  • HGet - 根据key和field字段,查询field字段的值
  • HGetAll - 根据key查询所有字段和值
  • HIncrBy - 根据key和field字段,累加数值。
  • HKeys - 根据key返回所有字段名
  • HLen - 根据key,查询hash的字段数量
  • HMGet - 根据key和多个字段名,批量查询多个hash字段值
  • HMSet - 根据key和多个字段名和字段值,批量设置hash字段值
  • HSetNX - 如果field字段不存在,则设置hash字段值
  • HDel - 根据key和字段名,删除hash字段,支持批量删除hash字段
  • HExists - 检测hash字段名是否存在。

提示:不管我们选择redis什么类型的数据,操作的时候都必须要有一个唯一的Key, 用来唯一标识一个数据。

1.HSet

根据key和field字段设置,field字段的值

// user_1 是hash key,username 是字段名, tizi365是字段值
err := client.HSet("user_1", "username", "tizi365").Err()
if err != nil {
	panic(err)
}

2.HGet

根据key和field字段,查询field字段的值

// user_1 是hash key,username是字段名
username, err := client.HGet("user_1", "username").Result()
if err != nil {
	panic(err)
}
fmt.Println(username)

3.HGetAll

根据key查询所有字段和值

// 一次性返回key=user_1的所有hash字段和值
data, err := client.HGetAll("user_1").Result()
if err != nil {
	panic(err)
}

// data是一个map类型,这里使用使用循环迭代输出
for field, val := range data {
	fmt.Println(field,val)
}

4.HIncrBy

根据key和field字段,累加字段的数值

// 累加count字段的值,一次性累加2, user_1为hash key
count, err := client.HIncrBy("user_1", "count", 2).Result()
if err != nil {
	panic(err)
}

fmt.Println(count)

5.HKeys

根据key返回所有字段名

// keys是一个string数组
keys, err := client.HKeys("user_1").Result()
if err != nil {
	panic(err)
}

fmt.Println(keys)

6.HLen

根据key,查询hash的字段数量

size, err := client.HLen("key").Result()
if err != nil {
	panic(err)
}

fmt.Println(size)

7.HMGet

根据key和多个字段名,批量查询多个hash字段值

// HMGet支持多个field字段名,意思是一次返回多个字段值
vals, err := client.HMGet("key","field1", "field2").Result()
if err != nil {
	panic(err)
}

// vals是一个数组
fmt.Println(vals)

8.HMSet

根据key和多个字段名和字段值,批量设置hash字段值

// 初始化hash数据的多个字段值
data := make(map[string]interface{})
data["id"] = 1
data["username"] = "tizi"

// 一次性保存多个hash字段值
err := client.HMSet("key", data).Err()
if err != nil {
	panic(err)
}

9.HSetNX

如果field字段不存在,则设置hash字段值

err := client.HSetNX("key", "id", 100).Err()
if err != nil {
	panic(err)
}

10.HDel

根据key和字段名,删除hash字段,支持批量删除hash字段

// 删除一个字段id
client.HDel("key", "id")

// 删除多个字段
client.HDel("key", "id", "username")

11.HExists

检测hash字段名是否存在。

// 检测id字段是否存在
err := client.HExists("key", "id").Err()
if err != nil {
	panic(err)
}