这是我参与「第三届青训营 -后端场」笔记创作活动的第8篇笔记;
整合redis相关操作
首先下载并导入相关依赖
首先下载第三方开源redis库:
go get github.com/garyburd/redigo/redis
导入:"github.com/garyburd/redigo/redis"
创建链接:
c, err := redis.Dial("tcp", "124.70.84.192:6380", redis.DialPassword("12345ssdlh"))
if err != nil {
fmt.Println(err)
return
}
//c即为链接
...
参数3用于进行一些普通的redis设置,如选择几号redis库,或者填写redis密码等,如下部分源码:
基本操作:
例如:操作set数据类型
defer c.Close()
//插入set类型值
_, err = c.Do("sadd", "1526676", "100", "ssw", "245", "109")
if err != nil {
fmt.Println(err)
return
}
//get得到set类型值
result, err := redis.Strings(c.Do("smembers", "1526676"))
//redis.Strings(...):redis对查询到的值进行相应的转换操作,有同样功能的还有redis.Float64s(),redis.Ints(),redis.Int()等等
if err != nil {
fmt.Println(err)
return
}
对于redis的操作都封装在了Do方法内,只要懂得一些基础的redis命令就可操作,还是非常具有灵活性的;其中Do方法第一个参数填写操作名值,之后的参数根据具体操作而调整;
其他数据类型参照以上,依此类推;
设置过期时间
同样也是用.Do()方法进行操作的,直接上代码:
c.Do("expire", "1526676", 30) //设置key为1526676的值30s后过期
r, err := redis.Int(c.Do("ttl", "1526676"))
fmt.Println("还有" + strconv.Itoa(r) + "秒该值过期")
//strconv.Itoa(r)将int类型转换为string
redis连接池
同mysql一样,进行连接最好还是用连接池,具体实现如下:
var redispool *redis.Pool
func init() {
redispool = &redis.Pool{
MaxIdle: 10, //设置最初连接数量
MaxActive: 0, //连接池最大连接数量,不确定用0(0表示按需分配)
IdleTimeout: 300, //超时时间,单位秒
Dial: func() (redis.Conn, error) { //配置要连接的数据库
return redis.Dial("tcp", "124.70.84.192:6380", redis.DialPassword("12345ssdlh"))
},
}
}
func main() {
c := redispool.Get() //从连接池获取一个连接
defer c.Close()
results, err := c.Do("sadd", "front", "123", "234", "278")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(results)
}
操作rabbitmq
RabbitMQ的基本结构:
组成部分说明:
- Broker:消息队列服务进程,此进程包括两个部分:Exchange和Queue
- Exchange:消息队列交换机,按一定的规则将消息路由转发到某个队列,对消息进行过虑。
- Queue:消息队列,存储消息的队列,消息到达队列并转发给指定的消息队列
- Producer:消息生产者,即生产方客户端,生产方客户端将消息发送
- Consumer:消息消费者,即消费方客户端,接收MQ转发的消息。 简单队列示例:
package main
import (
"fmt"
"github.com/streadway/amqp"
)
//连接信息
//格式“amqp://用户名:密码@ip:端口/路径”
const MQURL = "amqp://root:root@124.70.84.192:5672"
//构建rabbitmq结构体
type RabbitMQ struct {
conn *amqp.Connection
channel *amqp.Channel
//队列名称
QueryName string
//交换机名称
Exchange string
Key string
mqurl string
}
//创建rabbit结构体实例
func NewRabbitMQ(queueName string, exchange string, key string) *RabbitMQ {
return &RabbitMQ{QueryName: queueName, Exchange: exchange, Key: key}
}
//断开channel和connection
func (r *RabbitMQ) Destory() {
r.channel.Close()
r.conn.Channel()
}
//创建简单模式下RabbitMQ实例
func NewRabbitMQSimple(queueName string) *RabbitMQ {
//创建Rabbit实例
rabbitmq := NewRabbitMQ(queueName, "", "")
var err error
//获取连接,并将连接赋值到rabbit实例中
rabbitmq.conn, err = amqp.Dial(MQURL)
if err != nil {
fmt.Print("获取连接出错")
fmt.Println(err)
return nil
}
//获取channel,并将连接赋值到rabbit实例中
rabbitmq.channel, err = rabbitmq.conn.Channel()
if err != nil {
fmt.Print("获取channel失败")
fmt.Println(err)
return nil
}
return rabbitmq
}
//直接模式队列生产
func (r *RabbitMQ) PublishSimple(message string) {
//申请队列,如果存在则跳过,不存在则创建
_, err := r.channel.QueueDeclare(
r.QueryName,
false, //是否持久化
false, //是否自动删除
false, //是否具有排他性
false, //是否阻塞处理
nil, //额外属性
)
if err != nil {
fmt.Println(err)
return
}
//调用channel发送消息到队列中
r.channel.Publish(
r.Exchange,
r.QueryName,
false,
//如果为true,根据自身exchange类型和routekey规则
//无法找到符合条件的队列会把消息返还给发送者
false,
//如果为true,当exchange发送消息到队列后发现队列上没有消费者,则会把消息返还给发送者
amqp.Publishing{
ContentEncoding: "text/plain",
Body: []byte(message),
})
}
//simple模式消费者
func (r *RabbitMQ) ConsumerSimple() {
//申请队列,如果存在则跳过,不存在则创建
q, err := r.channel.QueueDeclare( //返回1个Queue
r.QueryName,
false, //是否持久化
false, //是否自动删除
false, //是否具有排他性
false, //是否阻塞处理
nil, //额外属性
)
if err != nil {
fmt.Println(err)
return
}
//接收消息
message, err := r.channel.Consume(
q.Name, //指定队列名
"", //consumer string
true, //是否自动应答
false, //是否独有
false, //设置为true,表示不能将同一个Conenction中生产者发送的消息传递给这个Connection中的消费者
false, //列是否阻塞
nil, //其他参数
)
if err != nil {
fmt.Println(err)
return
}
for d := range message {
fmt.Printf("消息是:%s", d.Body)
}
}
//主程序测试发送
func main() {
rabbitmq := NewRabbitMQSimple("apple")
rabbitmq.PublishSimple("hello,boy")
fmt.Println("已发送")
}
主程序测试接收:
//主程序测试消费者接收消息
func main() {
rabbitmq := NewRabbitMQSimple("apple")
rabbitmq.ConsumerSimple()
}