RabbitMQ常规操作(golang)

package RabbitMQ

import (
	"fmt"
	"github.com/streadway/amqp"
	"log"
)

//url 格式 amqp://账号:密码@rabbitmq服务地址:端口号/vhost
const MQURL = "amqp://imooc:imooc@127.0.0.1:5672/imooc"

type RabbitMQ struct {
	conn *amqp.Connection
	channel *amqp.Channel
	//队列名称
	QueueName string
	//交换机
	Exchange string
	//Key
	Key string
	//连接信息
	Mqurl string
}
//创建RabbitMQ结构体实例
func NewRabbitMQ(queueName string,exchange string,key string)*RabbitMQ  {
	rabbitmq := &RabbitMQ{
		QueueName: queueName,
		Exchange: exchange,
		Key: key,
		Mqurl: MQURL,
	}
	var err error
	rabbitmq.conn,err = amqp.Dial(rabbitmq.Mqurl)
	rabbitmq.failOnErr(err,"创建连接错误")
	rabbitmq.channel,err = rabbitmq.conn.Channel()
	rabbitmq.failOnErr(err,"获取channel失败")
	return rabbitmq
}

//断开channel和connection
func (r *RabbitMQ)Destory()  {
	r.channel.Close()
	r.conn.Close()
}

//错误处理函数
func (r *RabbitMQ)failOnErr(err error,message string)  {
	if err != nil{
		log.Fatalf("%s:%s",message,err)
		panic(fmt.Sprintf("%s:%s",message,err))
	}
}

//简单模式step: 1、创建简单模式下RabbitMQ实例
func NewRabbitMQSimple(queueName string)*RabbitMQ {
	rabbitmq := NewRabbitMQ(queueName,"","")
	return  rabbitmq
}
//简单模式step: 2.简单模式下生产代码
func (r *RabbitMQ)PublishSimple(message string)  {
	//1、申请队列,如果队列不错在会自动创建,如果存在则跳过创建
	//保证队列存在,消息能发送到队列
	_,err := r.channel.QueueDeclare(
		 r.QueueName,
		 //是否持久化
		 false,
		 //是否为自动删除
		 false,
		 //是否具有排他性
		 false,
		 //是否阻塞
		 false,
		 //额外属性
		 nil,
		)
	if err != nil{
		fmt.Println(err)
	}
	//2、发送消息到队列中
	r.channel.Publish(
		r.Exchange,
		r.QueueName,
		//如果为true,会根据exchange类型和routkey规则,如果无法找到符合条件的队列,那么会把消息返回给发送者
		false,
		//如果为true,当exchange发送消息到队列后发现队列上没有绑定消费者,则会把消息返回给发送者
		false,
		amqp.Publishing{
			ContentType: "text/plain",
			Body: []byte(message),
		},
		)
}
//简单模式step: 3.简单模式下消费代码
func (r *RabbitMQ)ConsumeSimple()  {
	//1、申请队列,如果队列不错在会自动创建,如果存在则跳过创建
	//保证队列存在,消息能发送到队列
	_,err := r.channel.QueueDeclare(
		r.QueueName,
		//是否持久化
		false,
		//是否为自动删除
		false,
		//是否具有排他性
		false,
		//是否阻塞
		false,
		//额外属性
		nil,
	)
	if err != nil{
		fmt.Println(err)
	}
	//接受消息
	msgs,err := r.channel.Consume(
			r.QueueName,
			//用来区分多个消费者
			"",
			//是否自动应答
			true,
			//是否具有排他性
			false,
			//如果设置为true,表示不能将同一个connection中发送的消息传递给这个connection中的消费者
			false,
			//队列消费是否阻塞
			false,
			nil,
		)
	if err != nil{
		fmt.Println(err)
	}
	forever := make(chan bool)
	//启用携程处理消息
	go func() {
		for d := range msgs{
			//实现我们要处理的逻辑函数
			log.Printf("Received a message:%s",d.Body)
		}

	}()
	log.Printf("[*] waiting for message,to exit")
	<-forever
}

//二:工作模式,work 一个消息只能被一个消费者获取(使用场景,生产消息的速度大于消费消息的速度)

//三:publish/subscribe,订阅模式
//消息被路由投递给多个队列,一个消息被多个消费者获取

//订阅模式下创建RabbitMQ实例
func NewRabbitMQPubSub(exchangeName string)*RabbitMQ  {
	//创建RabbitMQ实例
	rabbitmq := NewRabbitMQ("",exchangeName,"")
	var err error
	//获取connection
	rabbitmq.conn,err = amqp.Dial(rabbitmq.Mqurl)
	rabbitmq.failOnErr(err,"failed to connect rabbitmq!")
	//获取channel
	rabbitmq.channel,err = rabbitmq.conn.Channel()
	rabbitmq.failOnErr(err,"failed to open a channel")
	return rabbitmq
}

//订阅模式下生产
func (r *RabbitMQ)PublishPub(message string)  {
	//1、尝试创建交换机
	err := r.channel.ExchangeDeclare(
		r.Exchange,
		//广播类型
		"fanout",
		//是否持久化
		true,
		//是否自动删除
		false,
		//true表示这个exchange不可以被client用来推送消息,仅用来进行exchange和exchange之间的绑定
		false,
		false,
		nil,
		)
	r.failOnErr(err,"failed to declare an excha"+"nge")
	//2、发送消息
	err = r.channel.Publish(
		r.Exchange,
		"",
		//如果为true,会根据exchange类型和routkey规则,如果无法找到符合条件的队列,那么会把消息返回给发送者
		false,
		//如果为true,当exchange发送消息到队列后发现队列上没有绑定消费者,则会把消息返回给发送者
		false,
		amqp.Publishing{
			ContentType: "text/plain",
			Body: []byte(message),
		},
		)
}
//订阅模式消费代码
func (r *RabbitMQ)RecieveSub()  {
	//1、尝试创建交换机
	err := r.channel.ExchangeDeclare(
		r.Exchange,
		//广播类型
		"fanout",
		//是否持久化
		true,
		//是否自动删除
		false,
		//true表示这个exchange不可以被client用来推送消息,仅用来进行exchange和exchange之间的绑定
		false,
		false,
		nil,
	)
	r.failOnErr(err,"failed to declare an exchange")
	//2、试探性创建队列,这里注意队列的名称不要写
	q,err := r.channel.QueueDeclare(
		"", //随机生产队列名称
		false,
		false,
		//是否排他
		true,
		false,
		nil,
	)
	r.failOnErr(err,"failed to declare a queue")
	//绑定队列到exchange中
	err = r.channel.QueueBind(
		q.Name,
		//在PUB/SUB模式下,这里的KEY要为空
		"",
		r.Exchange,
		false,
		nil,
		)
	//消费消息
	message,err := r.channel.Consume(
		q.Name,
		"",
		true,
		false,
		false,
		false,
		nil,
		)
	forever := make(chan bool)
	go func() {
		for d := range message{
			log.Printf("received a message:%s",d.Body)
		}
	}()
	log.Printf("[*] waiting for message,to exit")
	<-forever
}

//四、Routing,路由模式
//一个消息被多个消费者获取。并且消息的目标队列可被生产者指定

//路由模式
//创建RabbitMQ实例
func NewRabbitMQRouting(exchangeName string,routingKey string)*RabbitMQ  {
	//创建RabbitMQ实例
	rabbitmq := NewRabbitMQ("",exchangeName,routingKey)
	var err error
	//获取connection
	rabbitmq.conn, err = amqp.Dial(rabbitmq.Mqurl)
	rabbitmq.failOnErr(err,"failed to connect rabbitmq!")
	//获取channel
	rabbitmq.channel,err = rabbitmq.conn.Channel()
	rabbitmq.failOnErr(err, "failed to open a channel")
	return rabbitmq
}
//路由模式发送消息
func (r *RabbitMQ)PublishRouting(message string)  {
	//1、尝试创建交换机
	err := r.channel.ExchangeDeclare(
		r.Exchange,
		//要改成direct
		"direct",
		//是否持久化
		true,
		//是否自动删除
		false,
		//true表示这个exchange不可以被client用来推送消息,仅用来进行exchange和exchange之间的绑定
		false,
		false,
		nil,
		)
	r.failOnErr(err,"failed to declare an exchange")
	//2、发送消息
	err = r.channel.Publish(
		r.Exchange,
		//要设置
		r.Key,
		false,
		false,
		amqp.Publishing{
			ContentType: "text/plain",
			Body: []byte(message),
		},
		)
	r.failOnErr(err,"failed to publish message")
}
//路由模式接受消息
func (r *RabbitMQ)RecieveRouting()  {
	//1、尝试创建交换机
	err := r.channel.ExchangeDeclare(
		r.Exchange,
		//要改成direct
		"direct",
		//是否持久化
		true,
		//是否自动删除
		false,
		//true表示这个exchange不可以被client用来推送消息,仅用来进行exchange和exchange之间的绑定
		false,
		false,
		nil,
		)
	r.failOnErr(err,"failed to declare an exchange")
	//2、试探性创建队列,这里注意队列名称不能写
	q,err := r.channel.QueueDeclare(
		"",//随机生产队列名称
		false,
		false,
		true,
		false,
		nil,
		)
	r.failOnErr(err,"failed to declare a queue")

	//绑定队列到exchange 中
	err = r.channel.QueueBind(
		q.Name,
		//需要绑定key
		r.Key,
		r.Exchange,
		false,
		nil,
		)
	//消费消息
	messages, err := r.channel.Consume(
		q.Name,
		"",
		true,
		false,
		false,
		false,
		nil,
		)
	forever := make(chan bool)
	go func() {
		for d := range messages{
			log.Printf("receive a message:%s",d.Body)
		}
	}()
	fmt.Println("退出请按CTRL+C\n")
	<-forever
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sillyyijia

互联网+乞讨

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值