blog.stackademic.com/design-patt… 构建器模式:
- 定义struct
- 定义接口,接口包含构建过程的步骤
- 实现接口
type QueueBuilder struct {
consume <-chan amqp.Delivery
queue *amqp.Queue
ch *amqp.Channel
errors []error
}
type IQueueBuilder interface {
InitChannel(conn *amqp.Connection) QueueBuilder
AddQueueDef(name string, durable, autoDelete, exclusive, noWait bool, args amqp.Table) QueueBuilder
AddListener() QueueBuilder
Build() (<-chan amqp.Delivery, *amqp.Channel, []error)
}
func (b QueueBuilder) InitChannel(conn *amqp.Connection) QueueBuilder {
ch, err := conn.Channel()
if err != nil {
b.errors = append(b.errors, err)
b.ch = nil
return b
}
b.ch = ch
return b
}
func (b QueueBuilder) AddQueueDef(
name string,
durable bool,
autoDelete bool,
exclusive bool,
noWait bool,
args amqp.Table) QueueBuilder {
if b.ch == nil {
b.errors = append(b.errors, errors.New("channel not initialized"))
return b
}
queue, err := b.ch.QueueDeclare(
name,
durable,
autoDelete,
exclusive,
noWait,
args,
)
if err != nil {
b.errors = append(b.errors, err)
}
b.queue = &queue
return b
}
func (b QueueBuilder) AddListener() QueueBuilder {
if len(b.errors) != 0 {
b.errors = append(b.errors, errors.New("error occurred in the previous step"))
return b
}
msgs, err := b.ch.Consume(
b.queue.Name,
"",
true, // Auto-acknowledge
false, // Exclusive
false, // No local
false, // No wait time
nil,
)
if err != nil {
b.errors = append(b.errors, err)
}
b.consume = msgs
return b
}
func (b QueueBuilder) Build() (<-chan amqp.Delivery, *amqp.Channel, []error) {
if len(b.errors) != 0 {
return nil, nil, b.errors
}
return b.consume, b.ch, nil
}
conn, err := amqp.Dial(amqpURI)
failOnError(err, "Failed to connect to RabbitMQ")
defer conn.Close()
var addQueue QueueBuilder
consume, ch, errs := addQueue.
InitChannel(conn).
AddQueueDef("add", false, false, false, false, nil).
AddListener().
Build()
if len(errs) != 0 {
for _, err := range errs {
log.Fatalf("%s", err)
}
panic("error for the 'add' queue")
}
var multQueue QueueBuilder
consumeMulti, chMulti, errs := multQueue.
InitChannel(conn).
AddQueueDef("mult", false, false, false, false, nil).
AddListener().
Build()
if len(errs) != 0 {
for _, err := range errs {
log.Fatalf("%s", err)
}
panic("error for the 'mult' queue")
}
var divQueue QueueBuilder
consumeDiv, chDiv, errs := divQueue.
InitChannel(conn).
AddQueueDef("div", false, false, false, false, nil).
AddListener().
Build()
if len(errs) != 0 {
for _, err := range errs {
log.Fatalf("%s", err)
}
panic("error for the 'div' queue")
}
// Start goroutines for each type of operation
go add(consume, ch)
go mult(consumeMulti, chMulti)
go div(consumeDiv, chDiv)
select {}