golang操作redis

Redis

点我去redis官网
点我查看redis命令参考
golang操作redis_第1张图片
golang操作redis_第2张图片
程序操作redis原理:

  • go代码发送指令到redis 6379端口
  • redis核心组件会维护一片内存对redis接收到的指令进行处理
  • 能够处理的数据大概为五种格式为: key-value格式
    string key-value
    hash[数据]
    list[数据]
    set集合[数据]
    zset有序集合[数据]
  • 处理完毕后进行持久化处理存入真正的库文件中.dbf .dbm等

golang操作redis_第3张图片
golang操作redis_第4张图片

基本使用案例:

添加key-val [set]

添加key-value指令为set,key为name,value为tom

127.0.0.1:6379> set key1 tom
OK

获取key对应的值

127.0.0.1:6379> get key1
"tom"

切换数据库
redis默认有16个数据库,切换数据库指令为 select,案例已经切换到1号库

127.0.0.1:6379> select 1
OK

查看当前数据库key-value键值对的数量
切换到0号库,使用dbsize查看当前库有多少对key-value,案例显示当前有一对

127.0.0.1:6379> dbsize
(integer) 1

清空当前库的key-value和清空所有库的key-value
清空当前库所有key-value flushdb

127.0.0.1:6379[1]> flushdb
OK

清空所有库所有key-value flushall

127.0.0.1:6379[1]> flushall
OK

redis五大基本数据类型和CRUD操作(增删改查)

golang操作redis_第5张图片


String字符串

golang操作redis_第6张图片
golang操作redis_第7张图片
如果key1已存在则set key1为修改key1的value,如果不存在则为创建一个key1

127.0.0.1:6379> set key1 jack
OK

del删除key则把这条key-value一起删除

127.0.0.1:6379> del key1
(integer) 1

golang操作redis_第8张图片
将值jack关联到键key1十秒后销毁此key-value

127.0.0.1:6379> setex key1 10 jack
OK

golang操作redis_第9张图片
mset [设置多对key-value]
mget [获取多对key-value]

127.0.0.1:6379> mset key1 tom key2 jack key3 tim
OK
127.0.0.1:6379> mget key1 key2 key3
1) "tom"
2) "jack"
3) "tim"

Hash哈希

golang操作redis_第10张图片
golang操作redis_第11张图片
golang操作redis_第12张图片
hash类似于golang中的map集合,示例person为key,name,age为field,tom,20为value [hset hget hdel]

127.0.0.1:6379> hset person name tom
(integer) 1
127.0.0.1:6379> hset person age 20
(integer) 1
127.0.0.1:6379> hget person name
"tom"
127.0.0.1:6379> hget person age
"20"
127.0.0.1:6379> hdel person name age address
(integer) 3

一次存放多对field-value [hmset]

127.0.0.1:6379> hmset person name tom age 20 address beijing
OK

hmget返回多个field的值[hmget]

127.0.0.1:6379> hmget person name age address
1) "tom"
2) "20"
3) "beijing"

返回hash字段person所有field-value信息 [hgetall]

127.0.0.1:6379> hgetall person
1) "name"
2) "tom"
3) "age"
4) "20"
5) "address"
6) "beijing"

返回hash字段person有几个字段 [hlen]

127.0.0.1:6379> hlen person
(integer) 3

返回person中是否有对应field [hexists]

127.0.0.1:6379> hexists person name
(integer) 1

List列表

golang操作redis_第13张图片
golang操作redis_第14张图片
存储操作,lpush代表从左边插入rpush代表右边插入 [lpush rpush]

127.0.0.1:6379> lpush fpx tian doinb lwx
(integer) 3
127.0.0.1:6379> rpush fpx Gimgoon
(integer) 4

取数据0 -1代表全部取出,先入后出类似栈,0是起始位 [lrange key 区间]

127.0.0.1:6379> lrange fpx 0 -1
1) "lwx"
2) "doinb"
3) "tian"
127.0.0.1:6379> lrange fpx 0 1
1) "lwx"
2) "doinb"

可以把list结构在redis中想象成一个头尾皆开的管道
golang操作redis_第15张图片
从左边移除并返回第一个元素 [lpop]

127.0.0.1:6379> lrange fpx 0 -1
1) "Crisp"
2) "lwx"
3) "doinb"
4) "tian"
5) "Gimgoon"
127.0.0.1:6379> lpop fpx
"Crisp"
127.0.0.1:6379> lrange fpx 0 -1
1) "lwx"
2) "doinb"
3) "tian"
4) "Gimgoon"

移除并返回列表 key 的尾元素 [rpop]

127.0.0.1:6379> lrange fpx 0 -1
1) "lwx"
2) "doinb"
3) "tian"
4) "Gimgoon"
127.0.0.1:6379> rpop fpx
"Gimgoon"
127.0.0.1:6379> lrange fpx 0 -1
1) "lwx"
2) "doinb"
3) "tian"

删除集合[del]
把key干掉,value也自动销毁gc

127.0.0.1:6379> del fpx
(integer) 1
127.0.0.1:6379> lrange fpx 0 -1
(empty list or set)

list注意事项

golang操作redis_第16张图片
注意
默认从左边向右取数据,lpush从左边存数据则后存现取,rpush从右边存数据则先存先取


Set集合

golang操作redis_第17张图片
golang操作redis_第18张图片
添加集合 [sadd]
sadd也可以用于修改覆盖操作

127.0.0.1:6379> sadd skt faker taddy kind otto
(integer) 4

返回集合所有元素 [smembers]

127.0.0.1:6379> smembers skt
1) "taddy"
2) "faker"
3) "otto"
4) "kind"

判断集合是否有指定元素 [sismember]

127.0.0.1:6379> sismember skt taddy
(integer) 1

删除指定集合元素 [srem]

127.0.0.1:6379> srem skt otto
(integer) 1
127.0.0.1:6379> smembers skt
1) "taddy"
2) "faker"
3) "kind"

go操作redis

golang操作redis_第19张图片
golang操作redis_第20张图片
golang操作redis_第21张图片
连接实例:

package main

import (
	"github.com/garyburd/redigo/redis"
	"fmt"
)

func main(){
	conn,err := redis.Dial("tcp","0.0.0.0:6379")
	defer conn.Close()

	if err != nil{
		fmt.Println("redis.Dial err:",err)
		return
	}
	fmt.Println("连接成功~~~",conn)
}

conn返回的这一坨就是连接到redis服务的连接套接字

PS E:\software\go-path\goproject\src\gojson\redis-11-5\main> go run .\main.go
连接成功~~~ &{{0 0} 0  0xc042070020 0 0xc0420900c0 0 0xc04204c140 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]}

向redis里添加获取数据:

package main

import (
	"github.com/garyburd/redigo/redis"
	"fmt"
)

func main(){
	conn,err := redis.Dial("tcp","0.0.0.0:6379")
	defer conn.Close()

	if err != nil{
		fmt.Println("redis.Dial err:",err)
		return
	}
	fmt.Println("连接成功!")

	// Do(commandName string, args ...interface{})(reply interface{}, err error)
	// commandName代表指令名 args ...interface{}代表任意类型可变长参数
	_ ,err = conn.Do("set","name","jack")
	if err != nil{
		fmt.Println("conn.Do err:",err)
		return
	}

	// redis.String是redis里自带的一个类型转化方法
	// conn.Do() 将指令发送到连接后将返回的数据转为string返回给r
	// r是一个接口如果把接口转为string容易出错
	// 如果是int类型则为redis.Int(),其他类型也是如此,如果是多个字符串则为redis.Strings()
	r,err := redis.String(conn.Do("get","name"))
	if err != nil{
		fmt.Println("conn.Do err:",err)
		return
	}

	fmt.Println("发送成功!")
	fmt.Println(r)
}
连接成功!
发送成功!
jack

注意

  • 由于发送指令返回值为接口,最好使用redis自己定义的类型转化方式返回后就直接转为想要的类型,然后再返回给接口,这样直接输出接口就好
  • 如果原数据直接返回给接口再进行转化可能会报类型转换异常
  • 最好使用redis原生方法进行操作

go程序操作hash

golang操作redis_第22张图片
单条hash插入取出:

_ ,err = conn.Do("hset","person","name","jack")
r,err := redis.String(conn.Do("hget","person","name"))

多条hash插入取出
注意:多条string字符串转换需要使用 redis.Strings()

_ ,err = conn.Do("hmset","person","name","jack","age","18","address","beijing")
r,err := redis.Strings(conn.Do("hmget","person","name","age","address"))

golang操作redis_第23张图片
golang操作redis_第24张图片
golang操作redis_第25张图片
golang操作redis_第26张图片


golang操作redis_第27张图片
解题思路:

  • 首先添加一个标准输入

  • 获取到用户输入后通过conn.Do发送指令给redis核心组件然后入库

  • 再通过conn.Do获取字段信息
    golang操作redis_第28张图片
    解题思路:

  • list类型 lpush是从左边存数据,rpush是从右边存数据

  • lrange是从左边取数据

  • 根据list类型在redis中的特征可以使用 rpush 存数据,lrange取数据即可实现先入先出取出用户最早浏览的数据

package main

import (
	"fmt"
	"github.com/garyburd/redigo/redis"
)

func list(conn redis.Conn){
	// rpush从右边入栈(管道)
	_,err := conn.Do("rpush","person","tom","19","beijing")
	if err != nil{
		fmt.Println("list.conn.Dial err",err)
	}
	// lrange从左边取数据(管道)
	r,err := redis.Strings(conn.Do("lrange","person",0,2))
	if err != nil{
		fmt.Println("redis.Strings err",err)
	}
	fmt.Println(r)
}

func main(){
	conn,err := redis.Dial("tcp","0.0.0.0:6379")
	defer conn.Close()
	if err != nil{
		fmt.Println("main.redis.Dial err",err)
		return
	}
	fmt.Println("redis连接成功!")

	list(conn)
}
redis连接成功!
[tom 19 beijing]

在这里插入图片描述


Redis连接池

golang操作redis_第29张图片

redis连接池理解:

  • 以前我们要通过程序对redis进行操作时就通过拨号redis.Dail()方法返回一个连接,使用完后就defer conn.Close
  • 有了连接池后提前建立好几个对redis的连接放入管道中,需要用就直接去拿,省去了即时建立连接的麻烦,效率更高,使用完后放回连接池
    golang操作redis_第30张图片

init函数解析:

  • 在go中,init和main函数都是特殊的存在,两者都不能定义参数和返回值,否则编译器直接报错。init函数在同一个包内,同一个文件内都可以定义多个init函数,且在包依赖情况时,会优先执行依赖包的init函数
  • init函数是用于程序执行前做包的初始化的函数,比如初始化包里的变量等
  • 每个包可以拥有多个init函数
  • 包的每个源文件也可以拥有多个init函数
  • 同一个包中多个init函数的执行顺序go语言没有明确的定义(说明)
  • 不同包的init函数按照包导入的依赖关系决定该初始化函数的执行顺序
  • init函数不能被其他函数调用,而是在main函数执行之前,自动被调用

redis连接池使用实例:

package main

import (
	"fmt"
	"github.com/garyburd/redigo/redis"
)

var pool *redis.Pool

// 程序启动初始化连接池
func init(){
	pool = &redis.Pool{
		// 最大空闲连接数
		MaxIdle : 8,
		// 表示和数据库的最大连接数,0表示不限制
		MaxActive : 0,
		// 最大空闲时间
		IdleTimeout : 100,
		// 初始化连接,表示连接到哪个地址
		Dial : func() (redis.Conn, error){
			return redis.Dial("tcp","0.0.0.0:6379")
		},
	}
}

func main(){
// 取出一个连接
	// func (p *Pool) Get() Conn {}
	// Get方法绑定的是指针类型Pool,所以实例化redis.Pool要实例化指针类型
	conn := pool.Get()
	defer conn.Close()

	_,err := conn.Do("set","name","jack")
	if err != nil{
		fmt.Println("conn.Do err = ",err)
	}
	s,err := redis.String(conn.Do("get","name"))
	if err != nil{
		fmt.Println("conn.Do err = ",err)
	}
	fmt.Println(s)
}
jack

个人理解redis连接池~后续补上

你可能感兴趣的:(go)