qdy пре 3 месеци
комит
59853f83ce
10 измењених фајлова са 993 додато и 0 уклоњено
  1. BIN
      .DS_Store
  2. 56
    0
      functions/exchange_functions.go
  3. 164
    0
      functions/message_functions.go
  4. 93
    0
      functions/queue_functions.go
  5. 74
    0
      functions/utility_functions.go
  6. 82
    0
      gct.sh
  7. 70
    0
      go.mod
  8. 234
    0
      go.sum
  9. 133
    0
      main.go
  10. 87
    0
      test/my_create_exchange_test.go

+ 56
- 0
functions/exchange_functions.go Прегледај датотеку

@@ -0,0 +1,56 @@
1
+package functions
2
+
3
+import (
4
+	"time"
5
+
6
+	"git.x2erp.com/qdy/go-base/types"
7
+	"git.x2erp.com/qdy/go-db/factory/rabbitmq"
8
+)
9
+
10
+// CreateExchange 创建交换机
11
+func CreateExchange(rabbitFactory *rabbitmq.RabbitMQFactory, req types.ExchangeRequest) *types.QueryResult {
12
+	// 设置默认值
13
+	if req.ChannelName == "" {
14
+		req.ChannelName = "default"
15
+	}
16
+	if req.ExchangeType == "" {
17
+		req.ExchangeType = "direct"
18
+	}
19
+
20
+	// 确保通道存在
21
+	_, err := rabbitFactory.CreateChannel(req.ChannelName)
22
+	if err != nil {
23
+		return &types.QueryResult{
24
+			Success: false,
25
+			Error:   "Failed to create channel: " + err.Error(),
26
+			Time:    time.Now().Format(time.RFC3339),
27
+		}
28
+	}
29
+
30
+	// 创建交换机
31
+	err = rabbitFactory.AddExchange(
32
+		req.ChannelName,
33
+		req.ExchangeName,
34
+		req.ExchangeType,
35
+		req.Durable,
36
+	)
37
+	if err != nil {
38
+		return &types.QueryResult{
39
+			Success: false,
40
+			Error:   "Failed to create exchange: " + err.Error(),
41
+			Time:    time.Now().Format(time.RFC3339),
42
+		}
43
+	}
44
+
45
+	return &types.QueryResult{
46
+		Success: true,
47
+		Message: "Exchange created successfully",
48
+		Time:    time.Now().Format(time.RFC3339),
49
+		Data: map[string]interface{}{
50
+			"exchange_name": req.ExchangeName,
51
+			"exchange_type": req.ExchangeType,
52
+			"durable":       req.Durable,
53
+			"channel":       req.ChannelName,
54
+		},
55
+	}
56
+}

+ 164
- 0
functions/message_functions.go Прегледај датотеку

@@ -0,0 +1,164 @@
1
+package functions
2
+
3
+import (
4
+	"encoding/json"
5
+	"time"
6
+
7
+	"git.x2erp.com/qdy/go-base/types"
8
+	"git.x2erp.com/qdy/go-db/factory/rabbitmq"
9
+	"github.com/streadway/amqp"
10
+)
11
+
12
+// SendMessage 发送JSON消息
13
+func SendMessage(rabbitFactory *rabbitmq.RabbitMQFactory, req types.MessageRequest) *types.QueryResult {
14
+	// 设置默认值
15
+	if req.ChannelName == "" {
16
+		req.ChannelName = "default"
17
+	}
18
+	if req.ExchangeName == "" {
19
+		req.ExchangeName = "" // 默认交换机
20
+	}
21
+	if req.ContentType == "" {
22
+		req.ContentType = "application/json"
23
+	}
24
+	if req.Timestamp.IsZero() {
25
+		req.Timestamp = time.Now()
26
+	}
27
+
28
+	// 确保通道存在
29
+	channel, err := rabbitFactory.GetChannel(req.ChannelName)
30
+	if err != nil {
31
+		return &types.QueryResult{
32
+			Success: false,
33
+			Error:   "Failed to get channel: " + err.Error(),
34
+			Time:    time.Now().Format(time.RFC3339),
35
+		}
36
+	}
37
+
38
+	// 序列化消息
39
+	messageBody, err := json.Marshal(req.Message)
40
+	if err != nil {
41
+		return &types.QueryResult{
42
+			Success: false,
43
+			Error:   "Failed to marshal message: " + err.Error(),
44
+			Time:    time.Now().Format(time.RFC3339),
45
+		}
46
+	}
47
+
48
+	// 创建消息
49
+	msg := amqp.Publishing{
50
+		ContentType:   req.ContentType,
51
+		Body:          messageBody,
52
+		Headers:       amqp.Table(req.Headers),
53
+		Priority:      req.Priority,
54
+		CorrelationId: req.CorrelationID,
55
+		ReplyTo:       req.ReplyTo,
56
+		Expiration:    req.Expiration,
57
+		MessageId:     req.MessageID,
58
+		Timestamp:     req.Timestamp,
59
+		Type:          req.Type,
60
+		AppId:         req.AppID,
61
+		DeliveryMode:  amqp.Persistent, // 持久化消息
62
+	}
63
+
64
+	// 发送消息
65
+	err = channel.Publish(
66
+		req.ExchangeName,
67
+		req.RoutingKey,
68
+		false, // mandatory
69
+		false, // immediate
70
+		msg,
71
+	)
72
+	if err != nil {
73
+		return &types.QueryResult{
74
+			Success: false,
75
+			Error:   "Failed to publish message: " + err.Error(),
76
+			Time:    time.Now().Format(time.RFC3339),
77
+		}
78
+	}
79
+
80
+	return &types.QueryResult{
81
+		Success: true,
82
+		Message: "Message sent successfully",
83
+		Time:    time.Now().Format(time.RFC3339),
84
+		Data: map[string]interface{}{
85
+			"exchange":     req.ExchangeName,
86
+			"routing_key":  req.RoutingKey,
87
+			"channel":      req.ChannelName,
88
+			"message_size": len(messageBody),
89
+			"content_type": req.ContentType,
90
+			"timestamp":    req.Timestamp.Format(time.RFC3339),
91
+			"MessageID":    req.MessageID,
92
+		},
93
+	}
94
+}
95
+
96
+// SendBytesMessage 发送字节消息
97
+func SendBytesMessage(rabbitFactory *rabbitmq.RabbitMQFactory, req types.BytesMessageRequest) *types.QueryResult {
98
+	// 设置默认值
99
+	if req.ChannelName == "" {
100
+		req.ChannelName = "default"
101
+	}
102
+	if req.ExchangeName == "" {
103
+		req.ExchangeName = ""
104
+	}
105
+	if req.ContentType == "" {
106
+		req.ContentType = "application/octet-stream"
107
+	}
108
+
109
+	// 确保通道存在
110
+	channel, err := rabbitFactory.GetChannel(req.ChannelName)
111
+	if err != nil {
112
+		return &types.QueryResult{
113
+			Success: false,
114
+			Error:   "Failed to get channel: " + err.Error(),
115
+			Time:    time.Now().Format(time.RFC3339),
116
+		}
117
+	}
118
+
119
+	// 创建消息
120
+	msg := amqp.Publishing{
121
+		ContentType:  req.ContentType,
122
+		Body:         req.Data,
123
+		Headers:      convertHeaders(req.Headers),
124
+		DeliveryMode: amqp.Persistent,
125
+	}
126
+
127
+	// 发送消息
128
+	err = channel.Publish(
129
+		req.ExchangeName,
130
+		req.RoutingKey,
131
+		false,
132
+		false,
133
+		msg,
134
+	)
135
+	if err != nil {
136
+		return &types.QueryResult{
137
+			Success: false,
138
+			Error:   "Failed to publish bytes message: " + err.Error(),
139
+			Time:    time.Now().Format(time.RFC3339),
140
+		}
141
+	}
142
+
143
+	return &types.QueryResult{
144
+		Success: true,
145
+		Message: "Bytes message sent successfully",
146
+		Time:    time.Now().Format(time.RFC3339),
147
+		Data: map[string]interface{}{
148
+			"exchange":     req.ExchangeName,
149
+			"routing_key":  req.RoutingKey,
150
+			"channel":      req.ChannelName,
151
+			"data_size":    len(req.Data),
152
+			"content_type": req.ContentType,
153
+		},
154
+	}
155
+}
156
+
157
+// 转换headers类型
158
+func convertHeaders(headers map[string]string) amqp.Table {
159
+	table := make(amqp.Table)
160
+	for k, v := range headers {
161
+		table[k] = v
162
+	}
163
+	return table
164
+}

+ 93
- 0
functions/queue_functions.go Прегледај датотеку

@@ -0,0 +1,93 @@
1
+package functions
2
+
3
+import (
4
+	"time"
5
+
6
+	"git.x2erp.com/qdy/go-base/types"
7
+	"git.x2erp.com/qdy/go-db/factory/rabbitmq"
8
+)
9
+
10
+// CreateQueue 创建队列
11
+func CreateQueue(rabbitFactory *rabbitmq.RabbitMQFactory, req types.QueueRequest) *types.QueryResult {
12
+	// 设置默认值
13
+	if req.ChannelName == "" {
14
+		req.ChannelName = "default"
15
+	}
16
+
17
+	// 确保通道存在
18
+	_, err := rabbitFactory.CreateChannel(req.ChannelName)
19
+	if err != nil {
20
+		return &types.QueryResult{
21
+			Success: false,
22
+			Error:   "Failed to create channel: " + err.Error(),
23
+			Time:    time.Now().Format(time.RFC3339),
24
+		}
25
+	}
26
+
27
+	// 创建队列
28
+	err = rabbitFactory.AddQueue(
29
+		req.ChannelName,
30
+		req.QueueName,
31
+		req.Durable,
32
+		req.Exclusive,
33
+		req.AutoDelete,
34
+	)
35
+	if err != nil {
36
+		return &types.QueryResult{
37
+			Success: false,
38
+			Error:   "Failed to create queue: " + err.Error(),
39
+			Time:    time.Now().Format(time.RFC3339),
40
+		}
41
+	}
42
+
43
+	return &types.QueryResult{
44
+		Success: true,
45
+		Message: "Queue created successfully",
46
+		Time:    time.Now().Format(time.RFC3339),
47
+		Data: map[string]interface{}{
48
+			"queue_name":  req.QueueName,
49
+			"durable":     req.Durable,
50
+			"exclusive":   req.Exclusive,
51
+			"auto_delete": req.AutoDelete,
52
+			"channel":     req.ChannelName,
53
+		},
54
+	}
55
+}
56
+
57
+// BindQueue 绑定队列到交换机
58
+func BindQueue(rabbitFactory *rabbitmq.RabbitMQFactory, req types.BindRequest) *types.QueryResult {
59
+	// 设置默认值
60
+	if req.ChannelName == "" {
61
+		req.ChannelName = "default"
62
+	}
63
+	if req.RoutingKey == "" {
64
+		req.RoutingKey = req.QueueName
65
+	}
66
+
67
+	// 绑定队列
68
+	err := rabbitFactory.BindQueue(
69
+		req.ChannelName,
70
+		req.QueueName,
71
+		req.ExchangeName,
72
+		req.RoutingKey,
73
+	)
74
+	if err != nil {
75
+		return &types.QueryResult{
76
+			Success: false,
77
+			Error:   "Failed to bind queue: " + err.Error(),
78
+			Time:    time.Now().Format(time.RFC3339),
79
+		}
80
+	}
81
+
82
+	return &types.QueryResult{
83
+		Success: true,
84
+		Message: "Queue bound to exchange successfully",
85
+		Time:    time.Now().Format(time.RFC3339),
86
+		Data: map[string]interface{}{
87
+			"queue":       req.QueueName,
88
+			"exchange":    req.ExchangeName,
89
+			"routing_key": req.RoutingKey,
90
+			"channel":     req.ChannelName,
91
+		},
92
+	}
93
+}

+ 74
- 0
functions/utility_functions.go Прегледај датотеку

@@ -0,0 +1,74 @@
1
+package functions
2
+
3
+import (
4
+	"encoding/json"
5
+	"net/http"
6
+	"time"
7
+
8
+	"git.x2erp.com/qdy/go-base/types"
9
+	"git.x2erp.com/qdy/go-db/factory/rabbitmq"
10
+)
11
+
12
+// HealthCheck RabbitMQ健康检查
13
+func HealthCheck(w http.ResponseWriter, r *http.Request, rabbitFactory *rabbitmq.RabbitMQFactory) {
14
+	w.Header().Set("Content-Type", "application/json")
15
+
16
+	// 尝试创建测试通道
17
+	_, err := rabbitFactory.CreateChannel("health_check")
18
+	if err != nil {
19
+		w.WriteHeader(http.StatusServiceUnavailable)
20
+		json.NewEncoder(w).Encode(map[string]interface{}{
21
+			"status": "down",
22
+			"error":  err.Error(),
23
+			"time":   time.Now().Format(time.RFC3339),
24
+		})
25
+		return
26
+	}
27
+
28
+	// 清理测试通道
29
+	rabbitFactory.CloseChannel("health_check")
30
+
31
+	w.WriteHeader(http.StatusOK)
32
+	json.NewEncoder(w).Encode(map[string]interface{}{
33
+		"status": "up",
34
+		"time":   time.Now().Format(time.RFC3339),
35
+	})
36
+}
37
+
38
+// GetQueueInfo 获取队列信息
39
+func GetQueueInfo(rabbitFactory *rabbitmq.RabbitMQFactory, req types.QueueInfoRequest) *types.QueryResult {
40
+	// 设置默认值
41
+	if req.ChannelName == "" {
42
+		req.ChannelName = "default"
43
+	}
44
+
45
+	// 获取通道
46
+	channel, err := rabbitFactory.GetChannel(req.ChannelName)
47
+	if err != nil {
48
+		return &types.QueryResult{
49
+			Success: false,
50
+			Error:   "Failed to get channel: " + err.Error(),
51
+			Time:    time.Now().Format(time.RFC3339),
52
+		}
53
+	}
54
+
55
+	// 获取队列信息
56
+	myQueue, err := channel.QueueInspect(req.QueueName)
57
+	if err != nil {
58
+		return &types.QueryResult{
59
+			Success: false,
60
+			Error:   "Failed to inspect queue: " + err.Error(),
61
+			Time:    time.Now().Format(time.RFC3339),
62
+		}
63
+	}
64
+
65
+	return &types.QueryResult{
66
+		Success: true,
67
+		Time:    time.Now().Format(time.RFC3339),
68
+		Data: map[string]interface{}{
69
+			"Consumers": myQueue.Consumers,
70
+			"Messages":  myQueue.Messages,
71
+			"Name":      myQueue.Name,
72
+		},
73
+	}
74
+}

+ 82
- 0
gct.sh Прегледај датотеку

@@ -0,0 +1,82 @@
1
+#!/bin/bash
2
+
3
+# 脚本用法:./git-commit-and-tag.sh "你的提交描述" "版本号"
4
+
5
+# 检查参数数量
6
+if [ $# -ne 2 ]; then
7
+    echo "错误: 脚本需要2个参数。"
8
+    echo "用法: $0 \"提交描述\" \"版本号\""
9
+    echo "示例: $0 \"修复了登录问题\" \"v1.2.3\""
10
+    exit 1
11
+fi
12
+
13
+# 分配参数
14
+COMMIT_MESSAGE="$1"
15
+VERSION_TAG="$2"
16
+
17
+# 检查当前目录是否为Git仓库
18
+if ! git rev-parse --git-dir > /dev/null 2>&1; then
19
+    echo "错误: 当前目录不是一个Git仓库。"
20
+    exit 1
21
+fi
22
+
23
+echo "开始处理提交和版本标签..."
24
+echo "提交描述: $COMMIT_MESSAGE"
25
+echo "版本标签: $VERSION_TAG"
26
+
27
+# 检查是否有未提交的更改
28
+if [ -n "$(git status --porcelain)" ]; then
29
+    echo "检测到未提交的更改,正在提交..."
30
+    
31
+    # 添加所有更改到暂存区
32
+    git add .
33
+    
34
+    # 进行提交
35
+    git commit -m "$COMMIT_MESSAGE"
36
+    if [ $? -ne 0 ]; then
37
+        echo "错误: 提交失败。"
38
+        exit 1
39
+    fi
40
+    echo "✅ 更改已提交"
41
+else
42
+    echo "提示: 没有未提交的更改,跳过提交步骤"
43
+    
44
+    # 检查是否有未提交的commit但未推送
45
+    LOCAL_COMMITS=$(git log @{u}..HEAD --oneline 2>/dev/null | wc -l)
46
+    if [ $LOCAL_COMMITS -eq 0 ]; then
47
+        echo "错误: 没有需要推送的提交。"
48
+        exit 1
49
+    else
50
+        echo "检测到 $LOCAL_COMMITS 个本地提交等待推送"
51
+    fi
52
+fi
53
+
54
+# 检查标签是否已存在
55
+if git rev-parse "$VERSION_TAG" >/dev/null 2>&1; then
56
+    echo "错误: 标签 '$VERSION_TAG' 已经存在。"
57
+    exit 1
58
+fi
59
+
60
+# 创建标签
61
+git tag "$VERSION_TAG"
62
+if [ $? -ne 0 ]; then
63
+    echo "错误: 创建标签失败。"
64
+    exit 1
65
+fi
66
+echo "✅ 标签 '$VERSION_TAG' 已创建"
67
+
68
+# 推送到远程仓库并推送标签
69
+echo "正在推送到远程仓库..."
70
+git push
71
+if [ $? -ne 0 ]; then
72
+    echo "错误: 推送提交失败。"
73
+    exit 1
74
+fi
75
+
76
+git push origin "$VERSION_TAG"
77
+if [ $? -ne 0 ]; then
78
+    echo "错误: 推送标签失败。"
79
+    exit 1
80
+fi
81
+
82
+echo "✅ 完成!提交已推送,版本标签 $VERSION_TAG 已创建并推送。"

+ 70
- 0
go.mod Прегледај датотеку

@@ -0,0 +1,70 @@
1
+module git.x2erp.com/qdy/go-svc-mqproducer
2
+
3
+go 1.25.4
4
+
5
+require (
6
+	git.x2erp.com/qdy/go-base v0.1.70
7
+	git.x2erp.com/qdy/go-db v0.1.70
8
+	github.com/streadway/amqp v1.1.0
9
+	go-micro.dev/v4 v4.11.0
10
+)
11
+
12
+require (
13
+	dario.cat/mergo v1.0.2 // indirect
14
+	github.com/Microsoft/go-winio v0.6.2 // indirect
15
+	github.com/ProtonMail/go-crypto v1.3.0 // indirect
16
+	github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da // indirect
17
+	github.com/bitly/go-simplejson v0.5.1 // indirect
18
+	github.com/cloudflare/circl v1.6.1 // indirect
19
+	github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
20
+	github.com/cyphar/filepath-securejoin v0.6.1 // indirect
21
+	github.com/emirpasic/gods v1.18.1 // indirect
22
+	github.com/fatih/color v1.9.0 // indirect
23
+	github.com/fsnotify/fsnotify v1.9.0 // indirect
24
+	github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
25
+	github.com/go-git/go-billy/v5 v5.6.2 // indirect
26
+	github.com/go-git/go-git/v5 v5.16.4 // indirect
27
+	github.com/go-micro/plugins/v4/registry/consul v1.2.1 // indirect
28
+	github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
29
+	github.com/golang/protobuf v1.5.4 // indirect
30
+	github.com/google/uuid v1.6.0 // indirect
31
+	github.com/hashicorp/consul/api v1.9.0 // indirect
32
+	github.com/hashicorp/go-cleanhttp v0.5.1 // indirect
33
+	github.com/hashicorp/go-hclog v0.12.0 // indirect
34
+	github.com/hashicorp/go-immutable-radix v1.0.0 // indirect
35
+	github.com/hashicorp/go-rootcerts v1.0.2 // indirect
36
+	github.com/hashicorp/golang-lru v0.5.3 // indirect
37
+	github.com/hashicorp/serf v0.9.5 // indirect
38
+	github.com/imdario/mergo v0.3.16 // indirect
39
+	github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
40
+	github.com/kevinburke/ssh_config v1.4.0 // indirect
41
+	github.com/klauspost/cpuid/v2 v2.3.0 // indirect
42
+	github.com/mattn/go-colorable v0.1.8 // indirect
43
+	github.com/mattn/go-isatty v0.0.20 // indirect
44
+	github.com/miekg/dns v1.1.68 // indirect
45
+	github.com/mitchellh/go-homedir v1.1.0 // indirect
46
+	github.com/mitchellh/hashstructure v1.1.0 // indirect
47
+	github.com/mitchellh/mapstructure v1.3.3 // indirect
48
+	github.com/nxadm/tail v1.4.11 // indirect
49
+	github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c // indirect
50
+	github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
51
+	github.com/pjbgf/sha1cd v0.5.0 // indirect
52
+	github.com/pkg/errors v0.9.1 // indirect
53
+	github.com/russross/blackfriday/v2 v2.1.0 // indirect
54
+	github.com/sergi/go-diff v1.4.0 // indirect
55
+	github.com/skeema/knownhosts v1.3.2 // indirect
56
+	github.com/urfave/cli/v2 v2.27.7 // indirect
57
+	github.com/xanzy/ssh-agent v0.3.3 // indirect
58
+	github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342 // indirect
59
+	golang.org/x/crypto v0.45.0 // indirect
60
+	golang.org/x/mod v0.30.0 // indirect
61
+	golang.org/x/net v0.47.0 // indirect
62
+	golang.org/x/sync v0.18.0 // indirect
63
+	golang.org/x/sys v0.38.0 // indirect
64
+	golang.org/x/text v0.31.0 // indirect
65
+	golang.org/x/tools v0.39.0 // indirect
66
+	google.golang.org/protobuf v1.36.10 // indirect
67
+	gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
68
+	gopkg.in/warnings.v0 v0.1.2 // indirect
69
+	gopkg.in/yaml.v2 v2.4.0 // indirect
70
+)

+ 234
- 0
go.sum Прегледај датотеку

@@ -0,0 +1,234 @@
1
+dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
2
+dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
3
+git.x2erp.com/qdy/go-base v0.1.70/go.mod h1:IYkjIY0xiqPKIOBojsR9miER2ceyly6+iwv4Zd64OT0=
4
+git.x2erp.com/qdy/go-db v0.1.70/go.mod h1:oApVuDJTvrJcsxmBunoUDAdC9GSFHR0MWrSZCfm89G0=
5
+github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
6
+github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
7
+github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
8
+github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw=
9
+github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
10
+github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
11
+github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
12
+github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I=
13
+github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
14
+github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
15
+github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
16
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
17
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
18
+github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
19
+github.com/bitly/go-simplejson v0.5.1 h1:xgwPbetQScXt1gh9BmoJ6j9JMr3TElvuIyjR8pgdoow=
20
+github.com/bitly/go-simplejson v0.5.1/go.mod h1:YOPVLzCfwK14b4Sff3oP1AmGhI9T9Vsg84etUnlyp+Q=
21
+github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
22
+github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
23
+github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
24
+github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
25
+github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE=
26
+github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc=
27
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
28
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
29
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
30
+github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o=
31
+github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
32
+github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
33
+github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
34
+github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
35
+github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
36
+github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
37
+github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
38
+github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
39
+github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
40
+github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
41
+github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
42
+github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
43
+github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
44
+github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
45
+github.com/go-git/go-git/v5 v5.16.4 h1:7ajIEZHZJULcyJebDLo99bGgS0jRrOxzZG4uCk2Yb2Y=
46
+github.com/go-git/go-git/v5 v5.16.4/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8=
47
+github.com/go-micro/plugins/v4/registry/consul v1.2.1 h1:3wctYMtstwQLCjoJ1HA6mKGGFF1hcdKDv5MzHakB1jE=
48
+github.com/go-micro/plugins/v4/registry/consul v1.2.1/go.mod h1:wTat7/K9XQ+i64VbbcMYFcEwipYfSgJM51HcA/sgsM4=
49
+github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
50
+github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
51
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
52
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
53
+github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
54
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
55
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
56
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
57
+github.com/hashicorp/consul/api v1.9.0 h1:T6dKIWcaihG2c21YUi0BMAHbJanVXiYuz+mPgqxY3N4=
58
+github.com/hashicorp/consul/api v1.9.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
59
+github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
60
+github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
61
+github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
62
+github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
63
+github.com/hashicorp/go-hclog v0.12.0 h1:d4QkX8FRTYaKaCZBoXYY8zJX2BXjWxurN/GA2tkrmZM=
64
+github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
65
+github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0=
66
+github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
67
+github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
68
+github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
69
+github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
70
+github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
71
+github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
72
+github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
73
+github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
74
+github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
75
+github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
76
+github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
77
+github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk=
78
+github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
79
+github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
80
+github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
81
+github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
82
+github.com/hashicorp/serf v0.9.5 h1:EBWvyu9tcRszt3Bxp3KNssBMP1KuHWyO51lz9+786iM=
83
+github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
84
+github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
85
+github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
86
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
87
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
88
+github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ=
89
+github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M=
90
+github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
91
+github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
92
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
93
+github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
94
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
95
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
96
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
97
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
98
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
99
+github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
100
+github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
101
+github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
102
+github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
103
+github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
104
+github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
105
+github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
106
+github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
107
+github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
108
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
109
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
110
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
111
+github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
112
+github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
113
+github.com/miekg/dns v1.1.68 h1:jsSRkNozw7G/mnmXULynzMNIsgY2dHC8LO6U6Ij2JEA=
114
+github.com/miekg/dns v1.1.68/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps=
115
+github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
116
+github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
117
+github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
118
+github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
119
+github.com/mitchellh/hashstructure v1.1.0 h1:P6P1hdjqAAknpY/M1CGipelZgp+4y9ja9kmUZPXP+H0=
120
+github.com/mitchellh/hashstructure v1.1.0/go.mod h1:xUDAozZz0Wmdiufv0uyhnHkUTN6/6d8ulp4AwfLKrmA=
121
+github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
122
+github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
123
+github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8=
124
+github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
125
+github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
126
+github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc=
127
+github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
128
+github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
129
+github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
130
+github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
131
+github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
132
+github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
133
+github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0=
134
+github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM=
135
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
136
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
137
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
138
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
139
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
140
+github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
141
+github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
142
+github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
143
+github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
144
+github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
145
+github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
146
+github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
147
+github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
148
+github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
149
+github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
150
+github.com/skeema/knownhosts v1.3.2 h1:EDL9mgf4NzwMXCTfaxSD/o/a5fxDw/xL9nkU28JjdBg=
151
+github.com/skeema/knownhosts v1.3.2/go.mod h1:bEg3iQAuw+jyiw+484wwFJoKSLwcfd7fqRy+N0QTiow=
152
+github.com/streadway/amqp v1.1.0 h1:py12iX8XSyI7aN/3dUT8DFIDJazNJsVJdxNVEpnQTZM=
153
+github.com/streadway/amqp v1.1.0/go.mod h1:WYSrTEYHOXHd0nwFeUXAe2G2hRnQT+deZJJf88uS9Bg=
154
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
155
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
156
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
157
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
158
+github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
159
+github.com/urfave/cli/v2 v2.27.7 h1:bH59vdhbjLv3LAvIu6gd0usJHgoTTPhCFib8qqOwXYU=
160
+github.com/urfave/cli/v2 v2.27.7/go.mod h1:CyNAG/xg+iAOg0N4MPGZqVmv2rCoP267496AOXUZjA4=
161
+github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
162
+github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
163
+github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342 h1:FnBeRrxr7OU4VvAzt5X7s6266i6cSVkkFPS0TuXWbIg=
164
+github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
165
+go-micro.dev/v4 v4.11.0 h1:DZ2xcr0pnZJDlp6MJiCLhw4tXRxLw9xrJlPT91kubr0=
166
+go-micro.dev/v4 v4.11.0/go.mod h1:eE/tD53n3KbVrzrWxKLxdkGw45Fg1qaNLWjpJMvIUF4=
167
+golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
168
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
169
+golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
170
+golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
171
+golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
172
+golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
173
+golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
174
+golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk=
175
+golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
176
+golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
177
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
178
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
179
+golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
180
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
181
+golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
182
+golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
183
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
184
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
185
+golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
186
+golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
187
+golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
188
+golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
189
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
190
+golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
191
+golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
192
+golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
193
+golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
194
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
195
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
196
+golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
197
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
198
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
199
+golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
200
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
201
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
202
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
203
+golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
204
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
205
+golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
206
+golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
207
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
208
+golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
209
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
210
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
211
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
212
+golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
213
+golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
214
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
215
+golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
216
+golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ=
217
+golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
218
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
219
+google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
220
+google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
221
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
222
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
223
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
224
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
225
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
226
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
227
+gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
228
+gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
229
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
230
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
231
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
232
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
233
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
234
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

+ 133
- 0
main.go Прегледај датотеку

@@ -0,0 +1,133 @@
1
+package main
2
+
3
+import (
4
+	"fmt"
5
+	"log"
6
+	"net/http"
7
+	"os"
8
+	"os/signal"
9
+	"syscall"
10
+
11
+	"git.x2erp.com/qdy/go-base/config"
12
+	"git.x2erp.com/qdy/go-base/middleware"
13
+	"git.x2erp.com/qdy/go-base/myservice"
14
+	"git.x2erp.com/qdy/go-db/factory/rabbitmq"
15
+	"git.x2erp.com/qdy/go-db/myhandle"
16
+	"git.x2erp.com/qdy/go-svc-mqproducer/functions"
17
+	"go-micro.dev/v4/web"
18
+)
19
+
20
+func main() {
21
+	cfg := config.GetConfig()
22
+	serviceConfig := cfg.GetService()
23
+
24
+	log.Printf("RabbitMQ Service Starting...")
25
+	log.Printf("Service Port: %d", serviceConfig.Port)
26
+	log.Printf("Service Name: %s", serviceConfig.ServiceName)
27
+
28
+	// 启动微服务
29
+	startRabbitMQService()
30
+}
31
+
32
+// 启动RabbitMQ微服务
33
+func startRabbitMQService() {
34
+	cfg := config.GetConfig()
35
+	//serviceConfig := cfg.GetService()
36
+
37
+	// 初始化RabbitMQ工厂
38
+	rabbitFactory, err := rabbitmq.NewRabbitMQFactory()
39
+	if err != nil {
40
+		log.Fatalf("Failed to create RabbitMQ factory: %v", err)
41
+	}
42
+	defer func() {
43
+		if err := rabbitFactory.Close(); err != nil {
44
+			log.Printf("RabbitMQ close error: %v", err)
45
+		}
46
+	}()
47
+
48
+	// 设置优雅关闭
49
+	setupGracefulShutdown(rabbitFactory)
50
+
51
+	// 创建默认通道
52
+	if err := createDefaultChannel(rabbitFactory); err != nil {
53
+		log.Fatalf("Failed to create default channel: %v", err)
54
+	}
55
+
56
+	webService := myservice.StartStandalone(cfg)
57
+
58
+	// 注册HTTP路由到webService
59
+	registerRabbitMQRoutes(webService, rabbitFactory)
60
+
61
+	// 等待服务运行
62
+	log.Printf("RabbitMQ Service started successfully")
63
+	log.Printf(" 	• Host: %s", cfg.GetRabbitMQ().Host)
64
+	log.Printf(" 	• Port: %d", cfg.GetRabbitMQ().Port)
65
+	log.Printf(" 	• Vhost: %s", cfg.GetRabbitMQ().Vhost)
66
+
67
+	// 保持主程序运行
68
+	select {}
69
+}
70
+
71
+// 创建默认通道
72
+func createDefaultChannel(rabbitFactory *rabbitmq.RabbitMQFactory) error {
73
+	_, err := rabbitFactory.CreateChannel("default")
74
+	if err != nil {
75
+		return fmt.Errorf("failed to create default channel: %v", err)
76
+	}
77
+	log.Println("Default RabbitMQ channel created successfully")
78
+	return nil
79
+}
80
+
81
+// 注册RabbitMQ相关路由
82
+func registerRabbitMQRoutes(webService web.Service, rabbitFactory *rabbitmq.RabbitMQFactory) {
83
+	// 创建交换机
84
+	webService.Handle("/api/rabbitmq/exchange/create", middleware.JWTAuthMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
85
+		myhandle.QueryHandlerJson(w, r, rabbitFactory, functions.CreateExchange)
86
+	})))
87
+
88
+	// 创建队列
89
+	webService.Handle("/api/rabbitmq/queue/create", middleware.JWTAuthMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
90
+		myhandle.QueryHandlerJson(w, r, rabbitFactory, functions.CreateQueue)
91
+	})))
92
+
93
+	// 绑定队列到交换机
94
+	webService.Handle("/api/rabbitmq/queue/bind", middleware.JWTAuthMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
95
+		myhandle.QueryHandlerJson(w, r, rabbitFactory, functions.BindQueue)
96
+	})))
97
+
98
+	// 发送JSON消息
99
+	webService.Handle("/api/rabbitmq/message/send", middleware.JWTAuthMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
100
+		myhandle.QueryHandlerJson(w, r, rabbitFactory, functions.SendMessage)
101
+	})))
102
+
103
+	// 发送原始消息(字节流)
104
+	webService.Handle("/api/rabbitmq/message/send-bytes", middleware.JWTAuthMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
105
+		myhandle.QueryHandlerJson(w, r, rabbitFactory, functions.SendBytesMessage)
106
+	})))
107
+
108
+	// 健康检查
109
+	webService.Handle("/api/rabbitmq/health", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
110
+		functions.HealthCheck(w, r, rabbitFactory)
111
+	}))
112
+
113
+	// 获取队列信息
114
+	webService.Handle("/api/rabbitmq/queue/info", middleware.JWTAuthMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
115
+		myhandle.QueryHandlerJson(w, r, rabbitFactory, functions.GetQueueInfo)
116
+	})))
117
+}
118
+
119
+// 设置优雅关闭
120
+func setupGracefulShutdown(rabbitFactory *rabbitmq.RabbitMQFactory) {
121
+	signalCh := make(chan os.Signal, 1)
122
+	signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM)
123
+
124
+	go func() {
125
+		<-signalCh
126
+		log.Println("\nReceived shutdown signal, closing RabbitMQ connections...")
127
+		if err := rabbitFactory.Close(); err != nil {
128
+			log.Printf("Error closing RabbitMQ: %v", err)
129
+		}
130
+		log.Println("RabbitMQ connections closed gracefully")
131
+		os.Exit(0)
132
+	}()
133
+}

+ 87
- 0
test/my_create_exchange_test.go Прегледај датотеку

@@ -0,0 +1,87 @@
1
+package test
2
+
3
+import (
4
+	"bytes"
5
+	"encoding/json"
6
+	"fmt"
7
+	"io"
8
+	"net/http"
9
+	"testing"
10
+	"time"
11
+)
12
+
13
+type ExchangeRequest struct {
14
+	ChannelName  string            `json:"channel_name"`
15
+	ExchangeName string            `json:"exchange_name"`
16
+	ExchangeType string            `json:"exchange_type"`
17
+	Durable      bool              `json:"durable"`
18
+	Internal     bool              `json:"internal"`
19
+	AutoDelete   bool              `json:"auto_delete"`
20
+	NoWait       bool              `json:"no_wait"`
21
+	Arguments    map[string]string `json:"arguments"`
22
+}
23
+
24
+func TestCreateexchange(t *testing.T) {
25
+	// 1. 准备请求数据
26
+	requestData := ExchangeRequest{
27
+		ChannelName:  "test_channel",
28
+		ExchangeName: "test_exchange",
29
+		ExchangeType: "direct", // direct, fanout, topic, headers
30
+		Durable:      true,
31
+		Internal:     false,
32
+		AutoDelete:   false,
33
+		NoWait:       false,
34
+		Arguments: map[string]string{
35
+			"x-delayed-type": "direct",
36
+		},
37
+	}
38
+
39
+	// 2. 将数据转换为JSON
40
+	jsonData, err := json.Marshal(requestData)
41
+	if err != nil {
42
+		fmt.Printf("JSON编码失败: %v\n", err)
43
+		return
44
+	}
45
+
46
+	// 3. 发送HTTP POST请求
47
+	url := "http://localhost:9090/api/rabbitmq/exchange/create"
48
+
49
+	// 如果服务端需要认证,添加JWT token
50
+	token := "your-jwt-token-here" // 替换为实际的JWT token
51
+
52
+	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
53
+	if err != nil {
54
+		fmt.Printf("创建请求失败: %v\n", err)
55
+		return
56
+	}
57
+
58
+	// 添加请求头
59
+	req.Header.Set("Content-Type", "application/json")
60
+	if token != "" {
61
+		req.Header.Set("Authorization", "Bearer "+token)
62
+	}
63
+
64
+	// 4. 发送请求并获取响应
65
+	client := &http.Client{
66
+		Timeout: 10 * time.Second,
67
+	}
68
+
69
+	resp, err := client.Do(req)
70
+	if err != nil {
71
+		fmt.Printf("请求失败: %v\n", err)
72
+		return
73
+	}
74
+	defer resp.Body.Close()
75
+
76
+	// 5. 读取响应
77
+	body, err := io.ReadAll(resp.Body)
78
+	if err != nil {
79
+		fmt.Printf("读取响应失败: %v\n", err)
80
+		return
81
+	}
82
+
83
+	// 6. 输出结果
84
+	fmt.Printf("状态码: %d\n", resp.StatusCode)
85
+	fmt.Printf("响应头: %v\n", resp.Header)
86
+	fmt.Printf("响应体: %s\n", string(body))
87
+}

Loading…
Откажи
Сачувај