【9.2】Golang后端开发系列--Gin路由定义与实战使用
文章目录
- 一、Gin 框架路由的基本定义方式
- 1. 简单路由创建
- 2. 路由参数
- 3. 查询参数
- 二、商业大项目中的路由定义和服务调用
- 1. 路由模块化
- 2. 路由组和中间件
- 3. 中间件的使用
- 4. 服务层调用
- 5. 错误处理
- 6. 版本控制
- 7. 路由注册
一、Gin 框架路由的基本定义方式
1. 简单路由创建
使用 gin.Default()
创建一个带有默认中间件的路由引擎,然后通过 GET
, POST
, PUT
, DELETE
等方法来定义不同 HTTP 方法的路由。
package mainimport ("github.com/gin-gonic/gin""net/http"
)func main() {// 创建带有默认中间件的路由引擎r := gin.Default()// 定义 GET 请求的路由r.GET("/hello", func(c *gin.Context) {c.String(http.StatusOK, "Hello, World!")})// 启动服务r.Run(":8080")
}
2. 路由参数
使用 :
来定义路由参数,通过 c.Param()
方法从请求中提取参数。
r.GET("/users/:userID", func(c *gin.Context) {userID := c.Param("userID")c.String(http.StatusOK, "User ID: %s", userID)
})
3. 查询参数
使用 c.Query()
方法来获取查询参数。
r.GET("/search", func(c *gin.Context) {query := c.Query("q")c.String(http.StatusOK, "Search query: %s", query)
})
二、商业大项目中的路由定义和服务调用
1. 路由模块化
为了使代码结构更清晰和易于维护,将路由定义分散到不同的文件和包中。
routes/user.go
package routesimport ("github.com/gin-gonic/gin""yourproject/services"
)func SetupUserRoutes(r *gin.RouterGroup) {r.GET("/", services.GetAllUsers)r.GET("/:id", services.GetUserByID)r.POST("/", services.CreateUser)r.PUT("/:id", services.UpdateUser)r.DELETE("/:id", services.DeleteUser)
}
services/user.go
package servicesimport ("github.com/gin-gonic/gin""net/http"
)func GetAllUsers(c *gin.Context) {// 调用数据访问层或其他服务层的函数来获取用户列表users, err := userService.GetAll()if err!= nil {c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch users"})return}c.JSON(http.StatusOK, users)
}func GetUserByID(c *gin.Context) {id := c.Param("id")user, err := userService.GetByID(id)if err!= nil {c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})return}c.JSON(http.StatusOK, user)
}func CreateUser(c *gin.Context) {var newUser Userif err := c.BindJSON(&newUser); err!= nil {c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid input"})return}if err := userService.Create(newUser); err!= nil {c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create user"})return}c.JSON(http.StatusCreated, gin.H{"message": "User created successfully"})
}func UpdateUser(c *gin.Context) {id := c.Param("id")var updatedUser Userif err := c.BindJSON(&updatedUser); err!= nil {c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid input"})return}if err := userService.Update(id, updatedUser); err!= nil {c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update user"})return}c.JSON(http.StatusOK, gin.H{"message": "User updated successfully"})
}func DeleteUser(c *gin.Context) {id := c.Param("id")if err := userService.Delete(id); err!= nil {c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete user"})return}c.JSON(http.StatusOK, gin.H{"message": "User deleted successfully"})
}
2. 路由组和中间件
使用路由组来组织相关的路由,并且可以为路由组添加中间件。
routes/router.go
package routesimport ("github.com/gin-gonic/gin""yourproject/middleware""yourproject/services"
)func SetupRoutes() *gin.Engine {r := gin.Default()// 公共中间件,例如日志、认证等r.Use(middleware.Logger(), middleware.Authenticate())// 用户路由组users := r.Group("/users")SetupUserRoutes(users)// 产品路由组products := r.Group("/products")SetupProductRoutes(products)return r
}
3. 中间件的使用
中间件可以在请求处理的不同阶段执行逻辑,如日志记录、认证、授权、错误处理等。
middleware/logger.go
package middlewareimport ("github.com/gin-gonic/gin""log""time"
)func Logger() gin.HandlerFunc {return func(c *gin.Context) {start := time.Now()c.Next()duration := time.Since(start)log.Printf("%s %s %s %v", c.Request.Method, c.Request.URL.Path, c.Writer.Status(), duration)}
}
middleware/authenticate.go
package middlewareimport ("github.com/gin-gonic/gin""net/http"
)func Authenticate() gin.HandlerFunc {return func(c *gin.Context) {// 检查用户是否认证,例如通过 token 验证if!isAuthenticated(c) {c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})return}c.Next()}
}func isAuthenticated(c *gin.Context) bool {// 实际的认证逻辑,例如检查请求头中的 tokenauthHeader := c.GetHeader("Authorization")if authHeader == "" {return false}// 更复杂的验证逻辑,如验证 token 的有效性return true
}
4. 服务层调用
将业务逻辑封装在服务层,路由处理函数负责调用相应的服务。
services/user_service.go
package servicesimport ("errors"
)type UserService struct{}func (s *UserService) GetAll() ([]User, error) {// 模拟从数据库或其他数据源获取用户列表// 这里应该调用实际的数据访问层函数users := []User{{ID: "1", Name: "Alice"},{ID: "2", Name: "Bob"},}return users, nil
}func (s *UserService) GetByID(id string) (*User, error) {// 模拟根据 ID 获取用户// 这里应该调用实际的数据访问层函数if id == "1" {return &User{ID: "1", Name: "Alice"}, nil}return nil, errors.New("User not found")
}func (s *UserService) Create(user User) error {// 模拟创建用户// 这里应该调用实际的数据访问层函数return nil
}func (s *UserService) Update(id string, user User) error {// 模拟更新用户// 这里应该调用实际的数据访问层函数return nil
}func (s *UserService) Delete(id string) error {// 模拟删除用户// 这里应该调用实际的数据访问层函数return nil
}
5. 错误处理
在路由处理函数和服务层中都要进行错误处理,确保将错误信息正确返回给客户端。
func GetUserByID(c *gin.Context) {id := c.Param("id")user, err := userService.GetByID(id)if err!= nil {c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})return}c.JSON(http.StatusOK, user)
}
6. 版本控制
对于 API 的不同版本,可以使用路由组进行管理。
func SetupRoutes() *gin.Engine {r := gin.Default()v1 := r.Group("/v1")SetupV1Routes(v1)v2 := r.Group("/v2")SetupV2Routes(v2)return r
}
7. 路由注册
在 main
函数中注册路由并启动服务。
package mainimport ("yourproject/routes"
)func main() {r := routes.SetupRoutes()r.Run(":8080")
}
通过上述方式,在商业大项目中使用 Gin 框架时,可以将路由定义、中间件、服务调用和错误处理等部分分离,实现清晰的分层架构,提高代码的可维护性和可扩展性。这样做有助于团队协作开发,并且方便对不同功能模块进行单独测试和优化。同时,合理使用路由组和中间件可以确保不同路由的逻辑隔离和功能复用。
相关文章:
【9.2】Golang后端开发系列--Gin路由定义与实战使用
文章目录 一、Gin 框架路由的基本定义方式1. 简单路由创建2. 路由参数3. 查询参数 二、商业大项目中的路由定义和服务调用1. 路由模块化2. 路由组和中间件3. 中间件的使用4. 服务层调用5. 错误处理6. 版本控制7. 路由注册 一、Gin 框架路由的基本定义方式 1. 简单路由创建 使…...
【微信小程序】let和const-综合实训
let 和 const 都是用于声明变量的关键字,它们与传统的 var 关键字相比,有很多不同之处。 let 声明块级作用域变量,可再赋值;const 声明块级作用域常量,不可再赋值。 以下是它们的详细介绍: 一、基本概念…...

图匹配算法(涵盖近似图匹配)
【图数据管理与挖掘-第四讲(子)图匹配算法(涵盖近似图匹配) 北京大学2021暑期-邹磊教授】https://www.bilibili.com/video/BV1zh411q7PW?vd_source7c2b5de7032bf3907543a7675013ce3a 图同构: 定义: 给定…...

java线程——Thread
java线程——Thread 基本步骤示例优劣总结 继承Thread类是Java中实现多线程的一种方式。使用时创建一个新的类,该类继承自java.lang.Thread,并重写其run()方法,在方法中定义线程执行的任务逻辑。 基本步骤 1、创建一个子类:定义一…...
MySQL8.0新特性
第十八章_MySQL8.0新特性 1.新特性概述 1. 数据库管理和存储 1.1 数据字典 特性: MySQL 8.0 使用统一的数据字典存储元数据(如表、列、索引等),并将其存储在 InnoDB 表中。 优点 : 提升性能:减少对文件系统的依赖。 提高一致…...

Oracle EBS GL定期盘存WIP日记账无法过账数据修复
系统环境 RDBMS : 12.1.0.2.0 Oracle Applications : 12.2.6 问题症状 用户反映来源为“定期盘存”和类别为“WIP”的日记账无法过账,标准日记账的界面上的过账按钮灰色不可用。但是,在超级用户职责下,该日记账又可以过账,细心检查发现该业务实体下有二个公司段值15100和…...
【绝对无坑】Mongodb获取集合的字段以及数据类型信息
Mongodb获取集合的字段以及数据类型信息 感觉很LOW的一个数据仓工具seatunel,竟然不能自动读取mongodb的表结构信息,需要手工创建。 然鹅,本人对mongodb也是新手,很多操作也不知所措,作为一个DBA,始终还是…...

【Git版本控制器--1】Git的基本操作--本地仓库
目录 初识git 本地仓库 认识工作区、暂存区、版本库 add操作与commit操作 master文件与commit id 修改文件 版本回退 撤销修改 删除文件 初识git Git 是一个分布式版本控制系统,主要用于跟踪文件的更改,特别是在软件开发中。 为什么要版本…...
C++并发编程之无锁数据结构及其优缺点
在C并发编程中,无锁数据结构(Lock-free Data Structures)是指那些在实现中不使用互斥锁(如std::mutex)来保证线程安全的数据结构。相反,它们利用原子操作和内存模型来确保多线程环境下的正确性和高效性。下…...

Ubuntu上,ffmpeg如何使用cuda硬件解码、编码、转码加速
本文使用 Ubuntu 环境。Ubuntu 直接使用 APT 安装的就支持 CUDA 加速。本文使用这样下载的版本进行演示,你自己编译或者其他源的版本可能会不同。 ffmpeg 的一些介绍,以及 macOS 版本的 ffmpeg 硬件加速请见《macOS上如何安装(不需要编译安装…...

rclone,云存储备份和迁移的瑞士军刀,千字常文解析,附下载链接和安装操作步骤...
一、什么是rclone? rclone是一个命令行程序,全称:rsync for cloud storage。是用于将文件和目录同步到云存储提供商的工具。因其支持多种云存储服务的备份,如Google Drive、Amazon S3、Dropbox、Backblaze B2、One Drive、Swift、…...
Ubuntu | 系统软件安装系列指导说明
文章目录 Ubuntu 系统软件安装系列指导说明工具系列1. Docker 与 Docker-Compose部署与安装 环境系列1. Golang部署与安装 数据库系列1. PostgreSQL17.2源码部署与安装 Ubuntu 系统软件安装系列指导说明 工具系列 1. Docker 与 Docker-Compose部署与安装 链接 环境系列 1…...

队列(算法十三)
简介 几乎没有单纯之考察队列的,队列一般只作为一个辅助工具 队列常服务于BFS queue接口 1.N叉树的层序遍历 link: 思路: 队列 层序遍历即可 code /* // Definition for a Node. class Node { public:int val;vector<Node*> children;Node()…...

vLLM私有化部署大语言模型LLM
目录 一、vLLM介绍 二、安装vLLM 1、安装环境 2、安装步骤 三、运行vLLM 1、运行方式 2、切换模型下载源 3、运行本地已下载模型 四、通过http访问vLLM 一、vLLM介绍 vLLM(官方网址:https://www.vllm.ai)是一种用于大规模语言模型&#x…...

OpenAI Whisper:语音识别技术的革新者—深入架构与参数
当下语音识别技术正以前所未有的速度发展,极大地推动了人机交互的便利性和效率。OpenAI的Whisper系统无疑是这一领域的佼佼者,它凭借其卓越的性能、广泛的适用性和创新的技术架构,正在重新定义语音转文本技术的规则。今天我们一起了解一下Whi…...

基于当前最前沿的前端(Vue3 + Vite + Antdv)和后台(Spring boot)实现的低代码开发平台
项目是一个基于当前最前沿的前端技术栈(Vue3 Vite Ant Design Vue,简称Antdv)和后台技术栈(Spring Boot)实现的低代码开发平台。以下是对该项目的详细介绍: 一、项目概述 项目名称:lowcode-s…...

【Rust】错误处理机制
目录 思维导图 引言 一、错误处理的重要性 1.1 软件中的错误普遍存在 1.2 编译时错误处理要求 二、错误的分类 2.1 可恢复错误(Recoverable Errors) 2.2 不可恢复错误(Unrecoverable Errors) 三、Rust 的错误处理机制 3…...

Logback日志技术
Logback日志技术 日志 日志(Logging)是软件开发和运维中用于记录系统或应用程序运行期间发生的运行信息、状态变化、错误信息等的一种机制,这种记录的方式就好像我们日常生活中写日记一样。它提供了一种持久化的方式,使得开发者…...
9分布式微服务架构
分布式微服务架构不光需要从架构上的设计优化系统,还要在编码上优化达到最好的效果 中心化的设计 中心化的设计比较简单,分布式集群中的角色分为两种,管理者和被管理者。 在一个分布式或者集群中,管理者角色管理着其他处理实际…...

Leecode刷题C语言之统计重新排列后包含另一个字符串的子字符串数目②
执行结果:通过 执行用时和内存消耗如下: void update(int *diff, int c, int add, int *cnt) {diff[c] add;if (add 1 && diff[c] 0) {// 表明 diff[c] 由 -1 变为 0(*cnt)--;} else if (add -1 && diff[c] -1) {// 表明 diff[c] 由 0 变为 -…...
STM32学习之I2C(理论篇)
📢:如果你也对机器人、人工智能感兴趣,看来我们志同道合✨ 📢:不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 📢:文章若有幸对你有帮助,可点赞 👍…...
NoSQL 之 Redis 配置与优化
目录 一、 前置知识点 1. 关系数据库与非关系型数据库 (1)关系型数据库 (2)非关系型数据库 (3)非关系型数据库产生背景 (4)两者对比 2. Redis 基础 (1࿰…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析LLP (二)
低层协议(Low Level Protocol, LLP)详细解析 1. 低层协议(Low Level Protocol, LLP)核心特性 包基础 :基于字节的包协议,支持 短包 (32位)和 长包 (可变长度࿰…...

什么是预训练?深入解读大模型AI的“高考集训”
1. 预训练的通俗理解:AI的“高考集训” 我们可以将预训练(Pre-training) 形象地理解为大模型AI的“高考集训”。就像学霸在高考前需要刷五年高考三年模拟一样,大模型在正式诞生前,也要经历一场声势浩大的“题海战术”…...

RAG检索系统的两大核心利器——Embedding模型和Rerank模型
在RAG系统中,有两个非常重要的模型一个是Embedding模型,另一个则是Rerank模型;这两个模型在RAG中扮演着重要角色。 Embedding模型的作用是把数据向量化,通过降维的方式,使得可以通过欧式距离,余弦函数等计算…...

一站式直播工具:助力内容创作者高效开启直播新时代
近年来,随着互联网技术的不断进步和短视频、直播行业的爆发式增长,越来越多的企业和个人投入到直播电商、互动娱乐、在线教育等场景。直播运营过程中,涉及到数据统计、弹幕互动、流程自动化、内容同步等诸多环节。如何提升运营效率、减少人工…...

增量式网络爬虫通用模板
之前做过一个项目,他要求是只爬取新产生的或者已经更新的页面,避免重复爬取未变化的页面,从而节省资源和时间。这里我需要设计一个增量式网络爬虫的通用模板。可以继承该类并重写部分方法以实现特定的解析和数据处理逻辑。这样可以更好的节约…...
STM32——CAN总线
STM32——CAN总线 1. CAN总线基础概念 1.1 CAN总线简介 控制器局域网(Controller Area Network, CAN)是由Bosch公司开发的串行通信协议,专为汽车电子和工业控制设计,具有以下核心特性: 多主控制架构:所有…...
Java 类型参数 T、R 、 O 、K、V 、E 、? 区别
在 Java 泛型和函数式编程中,T、R 和 O 都是类型参数(Type Parameters),它们的主要区别在于命名约定和上下文含义,而不是语言层面的区别。它们可以互换使用,但通常遵循一定的命名习惯以提高代码可读性。 1.…...
C#中的依赖注入
1. 依赖注入(Dependency Injection, DI)概述 定义 :依赖注入是一种设计模式,允许将组件的依赖关系从内部创建转移到外部提供。这样可以降低组件之间的耦合度,提高代码的可测试性、可维护性和可扩展性。 核心思想 &…...