【Golang】——Gin 框架中的路由与请求处理
文章目录
- 1. 路由基础
- 1.1 什么是路由?
- 1.2 Gin 中的路由概述
- 2. 创建简单路由
- 2.1 基本路由定义
- 2.2 不同请求方法的路由
- 3. 路由参数
- 3.1 路径参数
- 3.2 查询参数
- 4. 路由分组
- 4.1 为什么使用路由分组?
- 4.2 路由分组示例
- 5. 请求处理与响应
- 5.1 Gin 中的 Context 对象
- 5.2 JSON 响应
- 5.3 常见的响应方法
- 6. 实践示例:创建用户管理 API
- 6.1 API 功能需求
- 6.2 完整代码
- 6.3 代码解释
- 6.4 运行与测试
- 7. 总结
1. 路由基础
1.1 什么是路由?
在 Web 开发中,路由是指 URL 与请求处理函数之间的映射关系。通过路由,可以将客户端请求的路径映射到服务器端的特定处理逻辑,从而根据不同的路径和请求方法执行不同的操作。例如,当用户访问 /products
页面时,服务器可以响应商品数据,而访问 /users
则响应用户数据。
1.2 Gin 中的路由概述
Gin 框架中的路由机制十分灵活,支持以下几种特性:
- 路径参数:路径中可以带有动态的部分,例如
/users/:id
,:id
会被识别为动态参数。 - 查询参数:通常在 URL 中
?
后面指定,用于传递额外信息,例如/search?query=gin
。 - 分组路由:将具有相同前缀的路由分组,便于管理,例如
/v1/users
、/v1/products
等。
2. 创建简单路由
2.1 基本路由定义
在 Gin 中,可以使用 r.GET
、r.POST
等方法为不同的 HTTP 请求类型创建路由。下面是一个简单的示例代码,创建一个 GET 请求路由来响应根路径:
package mainimport ("github.com/gin-gonic/gin"
)func main() {// 使用 gin.Default() 创建带有默认中间件(日志和恢复中间件)的路由r := gin.Default()// 创建一个 GET 路由,匹配根路径 "/"r.GET("/", func(c *gin.Context) {// 使用 c.String() 返回纯文本内容,状态码为 200c.String(200, "欢迎使用 Gin 框架!")})// 启动 HTTP 服务,监听 8080 端口r.Run(":8080")
}
解释:
r := gin.Default()
:使用gin.Default()
方法初始化一个 Gin 引擎实例,包含了日志和崩溃恢复中间件。r.GET("/", func(c *gin.Context) {...})
:定义一个 GET 请求路由,匹配根路径/
。c.String(200, "...")
:返回状态码为 200 的纯文本响应。
2.2 不同请求方法的路由
Gin 提供了多种路由方法,分别对应不同的 HTTP 请求方法:
- GET:用于请求资源,例如获取用户数据。
- POST:用于提交新数据,例如新建用户。
- PUT:用于更新已有数据,例如修改用户信息。
- DELETE:用于删除数据,例如删除用户。
以下代码展示了如何使用不同的请求方法:
r.GET("/users", func(c *gin.Context) {c.String(200, "获取用户列表")
})r.POST("/users", func(c *gin.Context) {c.String(200, "创建新用户")
})r.PUT("/users/:id", func(c *gin.Context) {id := c.Param("id")c.String(200, "更新用户 %s 的信息", id)
})r.DELETE("/users/:id", func(c *gin.Context) {id := c.Param("id")c.String(200, "删除用户 %s", id)
})
3. 路由参数
3.1 路径参数
路径参数是一种在路径中传递动态数据的方式。例如 /users/:id
,其中 :id
是一个动态参数,可以捕获并在处理函数中使用:
r.GET("/users/:id", func(c *gin.Context) {// 使用 c.Param("id") 获取路径参数 id 的值id := c.Param("id")c.String(200, "用户 ID 是 %s", id)
})
示例说明:
- 当用户访问
/users/123
时,c.Param("id")
将会返回"123"
。 - 可以通过
id := c.Param("id")
获取到路径参数的值,进行进一步操作。
3.2 查询参数
查询参数用于在 URL 中传递额外数据,通常在路径后加上 ?
。例如 /search?query=gin
,query
为查询参数名,值为 "gin"
。Gin 可以通过 c.Query("参数名")
获取查询参数。
r.GET("/search", func(c *gin.Context) {query := c.Query("query")page := c.DefaultQuery("page", "1") // 设置默认值为 "1"c.String(200, "查询内容:%s,页码:%s", query, page)
})
示例说明:
- 使用
c.Query("query")
获取query
参数的值。 c.DefaultQuery("page", "1")
如果没有提供page
参数,则使用默认值"1"
。
4. 路由分组
4.1 为什么使用路由分组?
路由分组用于将具有相同前缀的路由划分为一个组,便于管理。比如一个 API 可能会有不同版本 /v1
和 /v2
,在不同版本中定义相似的路由,可以简化代码。
4.2 路由分组示例
以下代码展示了如何创建带有 /v1
和 /v2
前缀的路由分组:
v1 := r.Group("/v1")
{v1.GET("/users", func(c *gin.Context) {c.String(200, "获取 v1 版本的用户列表")})v1.POST("/users", func(c *gin.Context) {c.String(200, "在 v1 中创建新用户")})
}v2 := r.Group("/v2")
{v2.GET("/users", func(c *gin.Context) {c.String(200, "获取 v2 版本的用户列表")})
}
示例说明:
/v1
组内定义了用户列表的 GET 和 POST 路由。/v2
组内定义了用户列表的 GET 路由。- 这样便于管理不同 API 版本的路由。
5. 请求处理与响应
5.1 Gin 中的 Context 对象
Gin 中的 Context
对象封装了请求和响应。我们可以通过 Context
来获取请求信息并设置响应内容。Context
包含的常用方法有:
c.Param("参数名")
:获取路径参数。c.Query("参数名")
:获取查询参数。c.PostForm("参数名")
:获取 POST 请求的表单参数。c.JSON()
、c.XML()
、c.String()
:设置不同类型的响应内容。
5.2 JSON 响应
Gin 的 c.JSON()
方法可以用来返回 JSON 格式的数据:
r.GET("/json", func(c *gin.Context) {data := map[string]string{"message": "Hello, JSON"}c.JSON(200, data)
})
5.3 常见的响应方法
- 纯文本响应:
c.String()
,适用于返回简单的文本。 - JSON 响应:
c.JSON()
,用于返回结构化的 JSON 数据。 - XML 响应:
c.XML()
,用于返回 XML 格式的数据。 - 文件响应:
c.File()
,用于返回文件内容。
6. 实践示例:创建用户管理 API
6.1 API 功能需求
我们将实现一个简单的用户管理 API,包含以下功能:
- GET /user/:id - 获取用户信息。
- POST /user - 创建新用户。
- PUT /user/:id - 更新用户信息。
- DELETE /user/:id - 删除用户。
6.2 完整代码
以下是完整的代码示例:
package mainimport ("github.com/gin-gonic/gin"
)type User struct {ID string `json:"id"`Name string `json:"name"`Age int `json:"age"`
}var users = make(map[string]User)func main() {r := gin.Default()r.GET("/user/:id", func(c *gin.Context) {id := c.Param("id")if user, exists := users[id]; exists {c.JSON(200, user)} else {c.JSON(404, gin.H{"error": "User not found"})}})r.POST("/user", func(c *gin.Context)var newUser Userif err := c.ShouldBindJSON(&newUser); err == nil {users[newUser.ID] = newUserc.JSON(201, gin.H{"message": "User created successfully", "user": newUser})} else {c.JSON(400, gin.H{"error": err.Error()})}
})r.PUT("/user/:id", func(c *gin.Context) {id := c.Param("id")if user, exists := users[id]; exists {var updatedUser Userif err := c.ShouldBindJSON(&updatedUser); err == nil {user.Name = updatedUser.Nameuser.Age = updatedUser.Ageusers[id] = userc.JSON(200, gin.H{"message": "User updated successfully", "user": user})} else {c.JSON(400, gin.H{"error": err.Error()})}} else {c.JSON(404, gin.H{"error": "User not found"})}
})r.DELETE("/user/:id", func(c *gin.Context) {id := c.Param("id")if _, exists := users[id]; exists {delete(users, id)c.JSON(200, gin.H{"message": "User deleted successfully"})} else {c.JSON(404, gin.H{"error": "User not found"})}
})r.Run(":8080")
}
6.3 代码解释
- 结构体定义:
User
结构体表示用户信息,包含ID
、Name
和Age
。 - 全局变量:
users
是一个用于存储用户信息的 map,键是用户的ID
。 - GET 请求:
r.GET("/user/:id")
获取特定用户的详细信息。 - POST 请求:
r.POST("/user")
使用c.ShouldBindJSON(&newUser)
解析 JSON 请求体数据。 - PUT 请求:
r.PUT("/user/:id")
更新现有用户的信息。 - DELETE 请求:
r.DELETE("/user/:id")
删除指定的用户。
6.4 运行与测试
- 启动服务器:运行
go run main.go
。 - 使用 Postman 或
curl
进行请求测试:- 创建用户:
POST /user
请求体为{ "id": "1", "name": "Alice", "age": 25 }
- 获取用户:
GET /user/1
- 更新用户:
PUT /user/1
请求体为{ "name": "Alice Updated", "age": 26 }
- 删除用户:
DELETE /user/1
- 创建用户:
7. 总结
在本篇博客中,我们详细介绍了 Gin 框架中路由与请求处理的基础知识,并通过代码示例展示了如何实现一个用户管理 API。希望这些内容能帮助你掌握 Gin 路由的基本操作。下一篇将进一步探讨 Gin 的中间件使用,带你构建更加灵活、强大的 API 服务。
相关文章:

【Golang】——Gin 框架中的路由与请求处理
文章目录 1. 路由基础1.1 什么是路由?1.2 Gin 中的路由概述 2. 创建简单路由2.1 基本路由定义2.2 不同请求方法的路由 3. 路由参数3.1 路径参数3.2 查询参数 4. 路由分组4.1 为什么使用路由分组?4.2 路由分组示例 5. 请求处理与响应5.1 Gin 中的 Context…...

nuxt3添加wowjs动效
1、安装wowjs pnpm i wowjs1.1.32、node_modules复制wowjs代码 路径/node_modules/wowjs/dist/wow.js。不知道路径则查看node_modules/wowjs/package.json里面的main选项 2.1、在public文件夹创建wowjs.js文件 /public/wowjs.js export default (callthis) > { // !!// 这是…...

我们是如何实现 TiDB Cloud Serverless 的 - 成本篇
作者: shiyuhang0 原文来源: https://tidb.net/blog/fbedeea4 背景 Serverless 数据库是云原生时代的产物,它提供全托管,按需付费,自动弹性的云数据库服务,让客户免于繁重的数据库运维工作。关于 Serve…...

PCL算法汇总
参考 【2024最新版】PCL点云处理算法汇总(C长期更新版)_pcl点云聚类c-CSDN博客...

sql注入之二次注入(sqlilabs-less24)
二阶注入(Second-Order Injection)是一种特殊的 SQL 注入攻击,通常发生在用户输入的数据首先被存储在数据库中,然后在后续的操作中被使用时,触发了注入漏洞。与传统的 SQL 注入(直接注入)不同&a…...

Android compose 软键盘 遮挡对话框中TextField 输入框
在AlertDialog对话框中含有TextField输入框时,弹出软件盘会遮挡输入框 解决1: 在AndroidManifest.xml的 MainActivity中添加如下 android:windowSoftInputMode"adjustResize" 然后AlertDialog 中的modify. modify.windowInsetsP…...

spring-data-elasticsearch 3.2.4 实现桶bucket排序去重,实现指定字段的聚合搜索
一、背景 es索引有一个文档CourseIndex,下面是示意: creatorIdgradesubjectnameno1002270英语听力课程一N00232DS91004380数学口算课程N00209DK71003480物理竞赛课程N00642XS21002280英语听力课程二N00432WS31002290英语听力课程三N002312DP5 在搜索的时候&#…...

【项目开发】分析六种常用软件架构
未经许可,不得转载。 文章目录 软件架构核心内容设计原则分层架构常见层次划分优缺点应用场景事件驱动架构核心组件优缺点应用场景微核架构核心概念优缺点应用场景微服务架构核心组件设计与实施优缺点应用场景云架构云架构模式优缺点应用场景软件架构 软件架构是指一个软件系…...

算法和程序的区别
算法(Algorithm)和程序(Program)是计算机科学中两个密切相关但不同的概念。让我们通过以下几个方面来比较它们: ### 1. 设计 vs 实现 - **算法设计(Algorithm Design)**: - **定…...

用指针遍历数组
#include<stdio.h> int main() {//定义一个二维数组int arr[3][4] {{1,2,3,4},{2,3,4,5},{3,4,5,6},};//获取二维数组的指针int (*p)[4] arr;//二维数组里存的是一维数组int[4]for (int i 0; i < 3; i){//遍历一维数组for (int j 0; j <4; j){printf("%d &…...

《Probing the 3D Awareness of Visual Foundation Models》论文解析——多视图一致性
一、论文简介 论文讨论了大规模预训练产生的视觉基础模型在处理任意图像时的强大能力,这些模型不仅能够完成训练任务,其中间表示还对其他视觉任务(如检测和分割)有用。研究者们提出了一个问题:这些模型是否能够表示物体…...

使用pip安装esp32的擦除、写入固件的esptool库
esptool库可以为esp32的开发板烧录新的固件,但是如果为了烧录固件就要装esp-idf软件包,甚至需要用make编译安装很久,实在太费时费力了! 好消息就是,esp提供了python的esptool库,这样只要使用pip安装上这个…...

传奇996_23——杀怪掉落,自动捡取,捡取动画
一、杀怪掉落 前置: 添加地图地图刷怪怪物掉落(术语叫爆率,掉落叫爆率,而且文档上叫爆率) 刷怪步骤:在\MirServer\Mir200\Envir\MonItems文件夹中建立以怪物名字为文件名的txt文件写法案例: …...

【030】基于51单片机甲醛检测报警器【Proteus仿真+Keil程序+报告+原理图】
☆、设计硬件组成:51单片机最小系统 ZE08-CH2O甲醛传感器AT24C02存储芯片LCD1602液晶显示按键设置蜂鸣器报警。 1、本设计采用STC89C52、AT89C52、AT89S52作为主控芯片; 2、采用ZE08-CH2O甲醛传感器采集环境中的甲醛浓度值,LCD1602实时显示…...

微信小程序:vant组件库安装步骤
前言:在微信小程序中引用vant组件报错,提示路径不存在,这很有可能是因为没有安装构建vant组件库导致。下面是我整理的安装vant组件库的步骤: 第一步:安装node.js(执行完第一步请重启小程序) 具体步骤请看链接:node.js…...

处理namespace问题:Namespace not specified for AGP 8.0.0
How do I fix ‘namespace not specified’ error in Android Studio? Namespace not specified for AGP 8.0.0 解决方案 <?xml version"1.0" encoding"utf-8"?> <manifest xmlns:android"http://schemas.android.com/apk/res/androi…...

C++(Qt)软件调试---内存分析工具Heob(26)
C(Qt)软件调试—内存分析工具Heob(26) 文章目录 C(Qt)软件调试---内存分析工具Heob(26)[toc]1、概述🐜2、环境配置🪲3、功能说明4、使用Heob分析qt 程序内存泄漏🦧5、使用Heob检测qt 程序野指针…...

Redis五大基本类型——String字符串命令详解(命令用法详解+思维导图详解)
目录 一、String字符串类型介绍 二、常见命令 1、SET 2、GET 3、MGET 4、MSET 使用MGET 和 使用多次GET的区别 5、DEL 6、SETNX SET、SET NX和SET XX执行流程 7、INCR 8、INCRBY 9、DECR 10、DECYBY 11、INCRBYFLOAT 12、APPEND 13、GETRANGE 14、SETRANGE …...

Flutter中的Material Theme完全指南:从入门到实战
Flutter作为一款热门的跨平台开发框架,其UI组件库Material Design深受开发者喜爱。本文将深入探讨Flutter Material Theme的使用,包括如何借助Material Theme Builder创建符合产品需求的主题风格。通过多个场景和代码实例,让你轻松掌握这一工…...

Python 第三方库 PyQt5 的安装
目录 前言 PyQt5安装 不同操作系统PyQt5安装 一、Windows 系统 二、macOS 系统 三、Linux 系统(以 Ubuntu 为例) 安装 PyQt5 可能会遇到的问题 一、环境相关问题 二、依赖问题 三、网络问题 四、安装工具问题 五、运行时问题 六、环境配置问…...

CSS基础也要进行模电实验
盒子阴影 圆角边框已经介绍过哩,现在先介绍一下盒子阴影的效果如何实现 CSS3中新增了盒子阴影,可以使用box-shadow属性为盒子添加阴影 这是固定的语法: text-shadow: h-shadow v-shadow blur color; 它有这些可选的值: 哦。 …...

贴代码框架PasteForm特性介绍之markdown和richtext
简介 PasteForm是贴代码推出的 “新一代CRUD” ,基于ABPvNext,目的是通过对Dto的特性的标注,从而实现管理端的统一UI,借助于配套的PasteBuilder代码生成器,你可以快速的为自己的项目构建后台管理端!目前管…...

3D Gaussian Splatting 代码层理解之Part3
最后,内容到达了高斯泼溅过程中最有趣的阶段:渲染!这一步可以说是最关键的,因为它决定了模型的真实性。然而,它也可能是最简单的。在本系列的Part 1和Part2,文章演示了如何将 Raw 3D椭球 转换为可渲染的格式,但现在我们实际上必须完成这项工作并渲染到一组固定的像素上。…...

Ceph 中PG与PGP的概述
在Ceph分布式存储系统中,PG(Placement Group)和PGP(Placement Group for Placement purpose)是两个至关重要的概念,它们共同决定了数据在集群中的分布和复制方式。以下是关于Ceph中PG和PGP关系的详细解释&a…...

已解决:spark代码中sqlContext.createDataframe空指针异常
这段代码是使用local模式运行spark代码。但是在获取了spark.sqlContext之后,用sqlContext将rdd算子转换为Dataframe的时候报错空指针异常 Exception in thread "main" org.apache.spark.sql.AnalysisException: java.lang.RuntimeException: java.lang.Nu…...

flutter字体大小切换案例 小字体,标准字体,大字体,超大字体案例
flutter字体大小切换案例 小字体,标准字体,大字体,超大字体案例 Android iOS设备带有选择记录 我的flutter项目版本 environment: sdk: ‘>3.4.4 <4.0.0’ 图片案例 pubspec.yaml 添加依赖 # 屏幕尺寸适配 https://github.com/OpenF…...

智慧建造-运用Trimble技术将梦幻水族馆变为现实【上海沪敖3D】
项目概述 西雅图水族馆耗资1.6亿美元对海洋馆进行扩建。该项目包括建造三个大型栖息地,每个建筑物几乎都没有直边,其中一个主栖息地由520立方米混凝土和355吨钢筋组成。特纳建筑公司的混凝土团队通过强大的贸易合作伙伴和创新的数字制造技术,…...

【NOIP提高组】计算系数
【NOIP提高组】计算系数 C语言实现C实现Java实现Python实现 💐The Begin💐点点关注,收藏不迷路💐 给定一个多项式 (ax by)^k ,请求出多项式展开后 x^n y^m 项的系数。 输入 共一行,包含 5 个整数&#x…...

IDEA部署AI代写插件
前言 Hello大家好,当下是AI盛行的时代,好多好多东西在AI大模型的趋势下都变得非常的简单。 比如之前想画一幅风景画得先去采风,然后写实什么的,现在你只需描述出你想要的效果AI就能够根据你的描述在几分钟之内画出一幅你想要的风景…...

【阅读记录-章节1】Build a Large Language Model (From Scratch)
目录 1. Understanding large language models1.1 What is an LLM?补充介绍人工智能、机器学习和深度学习的关系机器学习 vs 深度学习传统机器学习 vs 深度学习(以垃圾邮件分类为例) 1.2 Applications of LLMs1.3 Stages of building and using LLMs1.4…...