快速掌握 GO 之 RabbitMQ 结合 gin+gorm 案例

更多个人笔记见:
注意点击“继续”,而不是“发现新项目”
github个人笔记仓库 https://github.com/ZHLOVEYY/IT_note
gitee 个人笔记仓库 https://gitee.com/harryhack/it_note
个人学习,学习过程中还会不断补充~ (后续会更新在github上)

文章目录

    • gin+gorm框架例子
        • 服务端生产者
        • 数据库存储
        • 客户端消费者
        • 访问测试

gin+gorm框架例子

post-platform/
├── main.go           # Gin 服务(生产者)
├── rabbitmq.go       # RabbitMQ 操作
├── models/
│   └── post.go       # 帖子模型
├── db/
│   └── db.go         # 数据库连接和操作
├── consumer/
│   └── main.go       # 消费者(存储到 MySQL)
├── go.mod
└── go.sum
服务端生产者
  • 定义 post.go

package modelstype Post struct {Title   string `json:"title"`Content string `json:"content"`
}

gin 框架:"go get github.com/gin-gonic/gin"

  • main.go:

package mainimport ("encoding/json""log""net/http""github.com/gin-gonic/gin""github.com/streadway/amqp"
)func failOnError(err error, msg string) {if err != nil {log.Fatalf("%s: %s", msg, err)}
}func main() {// 连接 RabbitMQconn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")failOnError(err, "Failed to connect to RabbitMQ")defer conn.Close()ch, err := conn.Channel()failOnError(err, "Failed to open a channel")defer ch.Close()q, err := ch.QueueDeclare("post_queue", false, false, false, false, nil)failOnError(err, "Failed to declare a queue")// 初始化 Ginr := gin.Default()// 提交帖子接口r.POST("/posts", func(c *gin.Context) {var post struct {Title   string `json:"title" binding:"required"`Content string `json:"content" binding:"required"`}if err := c.ShouldBindJSON(&post); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}// 序列化帖子为 JSONpostData, err := json.Marshal(post)if err != nil {c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to serialize post"})return}// 发送到 RabbitMQerr = ch.Publish("",     // 交换机q.Name, // 队列名称false,  // 强制false,  // 立即amqp.Publishing{ContentType: "application/json",Body:        postData,})if err != nil {c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to publish to RabbitMQ"})return}c.JSON(http.StatusOK, gin.H{"message": "Post submitted successfully"})})r.Run(":8081")
}
数据库存储

gorm 框架,需要 go get:

    "gorm.io/driver/mysql""gorm.io/gorm"
  • db.go
package dbimport ("log""test/model""gorm.io/driver/mysql""gorm.io/gorm"
)func InitDB() *gorm.DB {dsn := "root:password@tcp(localhost:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"//根据情况填写password 和 dbname(具体的数据库和密码),这里用的本地 sqldb, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})if err != nil {log.Fatalf("Failed to connect to database: %v", err)}// 自动迁移,创建 posts 表err = db.AutoMigrate(&model.Post{})if err != nil {log.Fatalf("Failed to migrate database: %v", err)}return db
}
客户端消费者
  • consumer.go
package mainimport ("encoding/json""log""test/db""github.com/streadway/amqp"
)func failOnError(err error, msg string) {if err != nil {log.Fatalf("%s: %s", msg, err)}
}type Post struct {Title   string `json:"title"`Content string `json:"content"`
}func main() {conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")failOnError(err, "Failed to connect to RabbitMQ")defer conn.Close()ch, err := conn.Channel()failOnError(err, "Failed to open a channel")defer ch.Close()q, err := ch.QueueDeclare("post_queue", false, false, false, false, nil)failOnError(err, "Failed to declare a queue")// 初始化数据库db := db.InitDB()//消费消息msgs, err := ch.Consume(q.Name, "", true, false, false, false, nil)failOnError(err, "Failed to register a consumer")forever := make(chan bool)go func() {for d := range msgs {var posts Postif err := json.Unmarshal(d.Body, &posts); err != nil {log.Printf("Failed to unmarshal post: %v", err)continue}// 存储到数据库if err := db.Create(&posts).Error; err != nil {log.Printf("Failed to save post to database: %v", err)continue}log.Printf("Received post: Title=%s, Content=%s", posts.Title, posts.Content)// TODO: 存储到数据库(如 MySQL)}}()log.Printf(" [*] Waiting for posts. To exit press CTRL+C")<-forever // 等待程序退出,防止主线程退出,主动阻塞
}

gorm 中的 Create 是只要结构体的名字一样就会找对应的表,所以结构体命名为 Post/Posts都可以,虽然和 model 中的不一样,但是如果名字不一样,Create 函数就“找不到”

访问测试

分别终端运行程序后:
地址:http://localhost:8081/posts
发送内容:

{"title": "My First Post","content": "Hello, world!"
}

可以发现能正确送达,同时能存储到数据库中

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/85641.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android FragmentManager 删除所有Fragment 重建

在Android开发中&#xff0c;管理Fragment是一项常见任务&#xff0c;有时需要删除所有Fragment并重新创建。这在某些场景下&#xff0c;例如用户需要重置应用状态或切换内容时&#xff0c;显得尤为重要。本文将详细介绍如何通过 FragmentManager删除所有Fragment并重建。 一、…

ubuntu之开机自启frpc

在 Ubuntu 系统中为 frpc 设置开机自启&#xff08;以 frpc -c frpc.toml 命令为例&#xff09;&#xff0c;可以通过 systemd 服务实现。以下是详细步骤&#xff1a; 创建 systemd 服务文件 sudo vim /etc/systemd/system/frpc.service 写入以下内容&#xff08;根据你的路…

推荐一款PDF压缩的工具

今天一位小伙伴找来&#xff0c;问我有没有办法将PDF变小的办法。 详细了解了一下使用场景&#xff1a; 小伙伴要在某系统上传一个PDF文件&#xff0c;原文件是11.6MB&#xff0c;但是上传时系统做了限制&#xff0c;只能上传小于10MB的文件&#xff0c;如图&#xff1a; 我听…

JDK21深度解密 Day 11:云原生环境中的JDK21应用

【JDK21深度解密 Day 111】云原生环境中的JDK21应用 本文是《JDK21深度解密:从新特性到生产实践的全栈指南》专栏的第11天内容,聚焦云原生环境中的JDK21应用。我们将深入探讨如何在容器化、微服务、Serverless等云原生架构中充分发挥JDK21的技术优势,提升Java应用的性能、稳…

Java-redis实现限时在线秒杀功能

1.使用redisson pom文件添加redisson <!--redisson--><dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.23.4</version></dependency> 2.mysql数据库表设…

QT- QML Layout+anchors 布局+锚点实现窗口部件权重比例分配

布局管理 简单比较两种界面管理锚点布局实现比例布局布局管理实现比例布局循环依赖问题简谈 在日常打螺丝中&#xff0c;我们偶尔会需要实现界面各组件能按比例放置&#xff0c;自适应各种分辨率的需求。我用锚点和布局都实现过相关界面&#xff0c;记录下来两种方式实现的差异…

Java项目OOM排查

排查思路 Java项目出现OOM&#xff08;Out Of Memory&#xff0c;内存溢出&#xff09;问题时&#xff0c;排查思路如下&#xff1a; 确认OOM类型&#xff1a; Java Heap Space&#xff1a;堆内存溢出&#xff0c;通常是对象创建过多或内存泄漏。PermGen Space&#xff1a;永久…

vue+threeJs 生成云状特效屏幕

嗨&#xff0c;我是小路。今天主要和大家分享的主题是“vuethreeJs 生成云状特效屏幕”。 动态云状特效示例图 二、实例代码 <!--创建一个动态数字屏幕--> <template><div class"pageBox"><div class"leftBox" ref"lef…

ABAP设计模式之---“高内聚,低耦合(High Cohesion Low Coupling)”

“高内聚、低耦合”是面向对象编程中非常重要的设计原则&#xff0c;它有助于提高代码的可维护性、扩展性和复用性。 1. 初衷&#xff1a;为什么会有这个原则&#xff1f; 在软件开发中&#xff0c;随着业务需求的复杂化&#xff0c;代码难免会变得越来越庞大。如果开发者将一…

Registry和docker有什么关系?

当遇到多个服务器需要同时传docker镜像的时候&#xff0c;一个一个的传效率会非常慢且压力完全在发送方的网络带宽&#xff1b;可以参考git hub&#xff0c;通常我们会用git push将代码传到git hub&#xff0c;如果谁需要代码用git pull就可以拉到自己的机器上&#xff0c;dock…

linux命令 systemctl 和 supervisord 区别及用法解读

目录 基础与背景服务管理范围配置文件和管理方式监控与日志依赖管理适用场景常用命令对照表实际应用场景举例优缺点对比小结参考链接 1. 基础与背景 systemctl 和 supervisord 都是用于管理和控制服务&#xff08;进程&#xff09;的工具&#xff0c;但它们在设计、使用场景和…

(11)java+ selenium->元素定位之By_tag_name

1.简介 继续WebDriver关于元素定位,这篇介绍By ClassName。tagName是DOM结构的一部分,其中页面上的每个元素都是通过输入标签,按钮标签或锚定标签等标签定义的。每个标签都具有多个属性,例如ID,名称,值类等。就其他定位符而言在Selenium中,我们使用了标签的这些属性值来…

2021 RoboCom 世界机器人开发者大赛-高职组(复赛)解题报告 | 珂学家

前言 题解 2021 RoboCom 世界机器人开发者大赛-高职组&#xff08;复赛&#xff09;解题报告。 模拟题为主&#xff0c;包含进制转换等等。 最后一题&#xff0c;是对向量/自定义类型&#xff0c;重定义小于操作符。 7-1 人工智能打招呼 分值: 15分 考察点: 分支判定&…

day42 简单CNN

目录 一、从图像分类任务谈起 二、CNN架构解剖实验室 2.1 卷积层&#xff1a;空间特征的魔法师 2.2 归一化层&#xff1a;加速收敛的隐形推手 2.3 激活函数&#xff1a;非线性的灵魂 三、工程实践避坑指南 3.1 数据增强工程 3.2 调度器工程实战 四、典型问题排查手册 …

Gitee Wiki:以知识管理赋能 DevSecOps,推动关键领域软件自主演进

关键领域软件研发中的知识管理困境 传统文档管理模式问题显著 关键领域软件研发领域&#xff0c;传统文档管理模式问题显著&#xff1a;文档存储无系统&#xff0c;查找困难&#xff0c;降低效率&#xff1b;更新不及时&#xff0c;与实际脱节&#xff0c;误导开发&#xff1…

清理 pycharm 无效解释器

1. 起因&#xff0c; 目的: 经常使用 pycharm 来调试深度学习项目&#xff0c;每次新建虚拟环境&#xff0c;都是显示一堆不存在的名称&#xff0c;删也删不掉。 总觉得很烦&#xff0c;是个痛点。决定深入研究一下。 2. 先看效果 效果是能行&#xff0c;而且清爽多了。 3. …

【ConvLSTM第二期】模拟视频帧的时序建模(Python代码实现)

目录 1 准备工作&#xff1a;python库包安装1.1 安装必要库 案例说明&#xff1a;模拟视频帧的时序建模ConvLSTM概述损失函数说明&#xff08;python全代码&#xff09; 参考 ConvLSTM的原理说明可参见另一博客-【ConvLSTM第一期】ConvLSTM原理。 1 准备工作&#xff1a;pytho…

MySQL DDL操作全解析:从入门到精通,包含索引视图分区表等全操作解析

目录 一、DDL 基础概述 1.1 DDL 定义与作用 1.2 DDL 语句分类 1.3 数据类型与存储引擎 1.3.1 数据类型 1.3.2 存储引擎差异 二、基础 DDL 语句详解 2.1 创建数据库与表 2.1.1 创建数据库 2.1.2 创建表 2.2 修改表结构 2.2.1 添加列 2.2.2 修改列属性 2.2.3 删除列…

设计模式——抽象工厂设计模式(创建型)

摘要 抽象工厂设计模式是一种创建型设计模式&#xff0c;旨在提供一个接口&#xff0c;用于创建一系列相关或依赖的对象&#xff0c;无需指定具体类。它通过抽象工厂、具体工厂、抽象产品和具体产品等组件构建&#xff0c;相比工厂方法模式&#xff0c;能创建一个产品族。该模…

Express教程【006】:使用Express写接口

文章目录 8、使用Express写接口8.1 创建API路由模块8.2 编写GET接口8.3 编写POST接口 8、使用Express写接口 8.1 创建API路由模块 1️⃣新建routes/apiRouter.js路由模块&#xff1a; /*** 路由模块*/ // 1-导入express const express require(express); // 2-创建路由对象…