Skip to content

Commit 3e1e744

Browse files
committed
feat: add rabbitmq direct exchange sample
add rabbitmq direct exchange sample add rabbitmq direct exchange sample
0 parents  commit 3e1e744

File tree

10 files changed

+506
-0
lines changed

10 files changed

+506
-0
lines changed

.gitignore

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# If you prefer the allow list template instead of the deny list, see community template:
2+
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
3+
#
4+
# Binaries for programs and plugins
5+
*.exe
6+
*.exe~
7+
*.dll
8+
*.so
9+
*.dylib
10+
11+
# Test binary, built with `go test -c`
12+
*.test
13+
14+
# Output of the go coverage tool, specifically when used with LiteIDE
15+
*.out
16+
17+
# Dependency directories (remove the comment below to include it)
18+
# vendor/
19+
20+
# Go workspace file
21+
go.work
22+
go.work.sum
23+
24+
# env file
25+
.env
26+
bin

Makefile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
.PHONY=build
2+
3+
build-producer:
4+
@CGO_ENABLED=0 GOOS=linux go build -o bin/producer producer/main.go
5+
6+
run-producer: build-producer
7+
@./bin/producer
8+
9+
build-consumer:
10+
@CGO_ENABLED=0 GOOS=linux go build -o bin/consumer consumer/main.go
11+
12+
run-consumer: build-consumer
13+
@./bin/consumer
14+
15+
coverage:
16+
@go test -v -cover ./...
17+
18+
test:
19+
@go test -v ./...
20+

README.md

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# golang-rabbitmq-sample
2+
3+
This is a example for use rabbitmq with golang
4+
5+
## asynchronize message pattern
6+
7+
![alt text](message-flow-pattern.png)
8+
9+
## use package
10+
11+
https://github.com/rabbitmq/amqp091-go
12+
13+
## install
14+
15+
```shell
16+
go get github.com/rabbitmq/amqp091-go
17+
go get github.com/gin-gonic/gin
18+
```
19+
20+
## producer logic
21+
22+
```golang
23+
package main
24+
25+
import (
26+
"fmt"
27+
"log"
28+
"net/http"
29+
"os"
30+
31+
"github.com/gin-gonic/gin"
32+
"github.com/leetcode-golang-classroom/golang-rabbitmq-sample/internal"
33+
amqp "github.com/rabbitmq/amqp091-go"
34+
)
35+
36+
func main() {
37+
// connect to rabbitmq
38+
conn, err := amqp.Dial(internal.AppConfig.RABBITMQ_URL)
39+
if err != nil {
40+
log.Fatal(err)
41+
}
42+
defer conn.Close()
43+
// open a channel
44+
channel, err := conn.Channel()
45+
if err != nil {
46+
log.Fatal(err)
47+
}
48+
defer channel.Close()
49+
// declare queue
50+
_, err = channel.QueueDeclare(internal.AppConfig.QUEUE_NAME, true, false, false, false, nil)
51+
if err != nil {
52+
log.Fatal(err)
53+
}
54+
55+
// create a web server with gin
56+
router := gin.Default()
57+
// add route for access request
58+
router.GET("/send", func(ctx *gin.Context) {
59+
msg := ctx.Query("msg")
60+
if msg == "" {
61+
ctx.JSON(http.StatusBadRequest, gin.H{"error": "Message is required"})
62+
return
63+
}
64+
// create a message to publish
65+
message := amqp.Publishing{
66+
ContentType: "text/plain",
67+
Body: []byte(msg),
68+
}
69+
// publish message to queue
70+
err = channel.Publish("", internal.AppConfig.QUEUE_NAME, false, false, message)
71+
if err != nil {
72+
// log.Printf("failed to publish message: %w", err)
73+
fmt.Fprintf(os.Stderr, "failed to publish message: %v", err)
74+
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to publish message"})
75+
return
76+
}
77+
ctx.JSON(http.StatusOK, gin.H{"message": msg, "status": "success"})
78+
})
79+
80+
log.Fatal(router.Run(fmt.Sprintf(":%v", internal.AppConfig.PORT)))
81+
}
82+
```
83+
84+
## consumer logic
85+
```golang
86+
package main
87+
88+
import (
89+
"log"
90+
"os"
91+
"os/signal"
92+
"syscall"
93+
94+
"github.com/leetcode-golang-classroom/golang-rabbitmq-sample/internal"
95+
amqp "github.com/rabbitmq/amqp091-go"
96+
)
97+
98+
func main() {
99+
// connect to rabbitmq
100+
conn, err := amqp.Dial(internal.AppConfig.RABBITMQ_URL)
101+
if err != nil {
102+
log.Fatal(err)
103+
}
104+
defer conn.Close()
105+
// open a channel
106+
channel, err := conn.Channel()
107+
if err != nil {
108+
log.Fatal(err)
109+
}
110+
defer channel.Close()
111+
// subscribe the message to the queue
112+
messages, err := channel.Consume(internal.AppConfig.QUEUE_NAME, "", true, false, false, false, nil)
113+
if err != nil {
114+
log.Fatal(err)
115+
}
116+
signChan := make(chan os.Signal, 1)
117+
signal.Notify(signChan, syscall.SIGINT, syscall.SIGTERM)
118+
119+
for {
120+
select {
121+
case message := <-messages:
122+
log.Printf("Message: %s\n", message.Body)
123+
case <-signChan:
124+
log.Println("Interrupt detected")
125+
os.Exit(0)
126+
}
127+
}
128+
}
129+
```

consumer/main.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package main
2+
3+
import (
4+
"log"
5+
"os"
6+
"os/signal"
7+
"syscall"
8+
9+
"github.com/leetcode-golang-classroom/golang-rabbitmq-sample/internal"
10+
amqp "github.com/rabbitmq/amqp091-go"
11+
)
12+
13+
func main() {
14+
// connect to rabbitmq
15+
conn, err := amqp.Dial(internal.AppConfig.RABBITMQ_URL)
16+
if err != nil {
17+
log.Fatal(err)
18+
}
19+
defer conn.Close()
20+
// open a channel
21+
channel, err := conn.Channel()
22+
if err != nil {
23+
log.Fatal(err)
24+
}
25+
defer channel.Close()
26+
// subscribe the message to the queue
27+
messages, err := channel.Consume(internal.AppConfig.QUEUE_NAME, "", true, false, false, false, nil)
28+
if err != nil {
29+
log.Fatal(err)
30+
}
31+
signChan := make(chan os.Signal, 1)
32+
signal.Notify(signChan, syscall.SIGINT, syscall.SIGTERM)
33+
34+
for {
35+
select {
36+
case message := <-messages:
37+
log.Printf("Message: %s\n", message.Body)
38+
case <-signChan:
39+
log.Println("Interrupt detected")
40+
os.Exit(0)
41+
}
42+
}
43+
}

docker-compose.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
services:
2+
rabbitmq:
3+
image: rabbitmq:3.11-management-alpine
4+
container_name: rabbitmq-sample
5+
environment:
6+
RABBITMQ_DEFAULT_USER: guest
7+
RABBITMQ_DEFAULT_PASS: guest
8+
healthcheck:
9+
test: rabbitmq-diagnostics -q ping
10+
interval: 30s
11+
timeout: 30s
12+
retries: 3
13+
ports:
14+
- 5672:5672
15+
- 15672:15672
16+
restart: always
17+
logging:
18+
driver: "json-file"
19+
options:
20+
max-size: "1k"
21+
max-file: "3"

go.mod

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
module github.com/leetcode-golang-classroom/golang-rabbitmq-sample
2+
3+
go 1.22.4
4+
5+
require (
6+
github.com/bytedance/sonic v1.11.6 // indirect
7+
github.com/bytedance/sonic/loader v0.1.1 // indirect
8+
github.com/cloudwego/base64x v0.1.4 // indirect
9+
github.com/cloudwego/iasm v0.2.0 // indirect
10+
github.com/fsnotify/fsnotify v1.7.0 // indirect
11+
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
12+
github.com/gin-contrib/sse v0.1.0 // indirect
13+
github.com/gin-gonic/gin v1.10.0 // indirect
14+
github.com/go-playground/locales v0.14.1 // indirect
15+
github.com/go-playground/universal-translator v0.18.1 // indirect
16+
github.com/go-playground/validator/v10 v10.20.0 // indirect
17+
github.com/goccy/go-json v0.10.2 // indirect
18+
github.com/hashicorp/hcl v1.0.0 // indirect
19+
github.com/json-iterator/go v1.1.12 // indirect
20+
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
21+
github.com/leodido/go-urn v1.4.0 // indirect
22+
github.com/magiconair/properties v1.8.7 // indirect
23+
github.com/mattn/go-isatty v0.0.20 // indirect
24+
github.com/mitchellh/mapstructure v1.5.0 // indirect
25+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
26+
github.com/modern-go/reflect2 v1.0.2 // indirect
27+
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
28+
github.com/rabbitmq/amqp091-go v1.10.0 // indirect
29+
github.com/sagikazarmark/locafero v0.4.0 // indirect
30+
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
31+
github.com/sourcegraph/conc v0.3.0 // indirect
32+
github.com/spf13/afero v1.11.0 // indirect
33+
github.com/spf13/cast v1.6.0 // indirect
34+
github.com/spf13/pflag v1.0.5 // indirect
35+
github.com/spf13/viper v1.19.0 // indirect
36+
github.com/subosito/gotenv v1.6.0 // indirect
37+
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
38+
github.com/ugorji/go/codec v1.2.12 // indirect
39+
go.uber.org/atomic v1.9.0 // indirect
40+
go.uber.org/multierr v1.9.0 // indirect
41+
golang.org/x/arch v0.8.0 // indirect
42+
golang.org/x/crypto v0.23.0 // indirect
43+
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
44+
golang.org/x/net v0.25.0 // indirect
45+
golang.org/x/sys v0.20.0 // indirect
46+
golang.org/x/text v0.15.0 // indirect
47+
google.golang.org/protobuf v1.34.1 // indirect
48+
gopkg.in/ini.v1 v1.67.0 // indirect
49+
gopkg.in/yaml.v3 v3.0.1 // indirect
50+
)

0 commit comments

Comments
 (0)