当前位置: 首页 > news >正文

【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 框架中的路由机制十分灵活,支持以下几种特性:

  1. 路径参数:路径中可以带有动态的部分,例如 /users/:id:id 会被识别为动态参数。
  2. 查询参数:通常在 URL 中 ? 后面指定,用于传递额外信息,例如 /search?query=gin
  3. 分组路由:将具有相同前缀的路由分组,便于管理,例如 /v1/users/v1/products 等。

2. 创建简单路由

2.1 基本路由定义

在 Gin 中,可以使用 r.GETr.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=ginquery 为查询参数名,值为 "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,包含以下功能:

  1. GET /user/:id - 获取用户信息。
  2. POST /user - 创建新用户。
  3. PUT /user/:id - 更新用户信息。
  4. 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 结构体表示用户信息,包含 IDNameAge
  • 全局变量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 运行与测试

  1. 启动服务器:运行 go run main.go
  2. 使用 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》论文解析——多视图一致性

一、论文简介 论文讨论了大规模预训练产生的视觉基础模型在处理任意图像时的强大能力&#xff0c;这些模型不仅能够完成训练任务&#xff0c;其中间表示还对其他视觉任务&#xff08;如检测和分割&#xff09;有用。研究者们提出了一个问题&#xff1a;这些模型是否能够表示物体…...

使用pip安装esp32的擦除、写入固件的esptool库

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

传奇996_23——杀怪掉落,自动捡取,捡取动画

一、杀怪掉落 前置&#xff1a; 添加地图地图刷怪怪物掉落&#xff08;术语叫爆率&#xff0c;掉落叫爆率&#xff0c;而且文档上叫爆率&#xff09; 刷怪步骤&#xff1a;在\MirServer\Mir200\Envir\MonItems文件夹中建立以怪物名字为文件名的txt文件写法案例&#xff1a; …...

【030】基于51单片机甲醛检测报警器【Proteus仿真+Keil程序+报告+原理图】

☆、设计硬件组成&#xff1a;51单片机最小系统 ZE08-CH2O甲醛传感器AT24C02存储芯片LCD1602液晶显示按键设置蜂鸣器报警。 1、本设计采用STC89C52、AT89C52、AT89S52作为主控芯片&#xff1b; 2、采用ZE08-CH2O甲醛传感器采集环境中的甲醛浓度值&#xff0c;LCD1602实时显示…...

微信小程序:vant组件库安装步骤

前言&#xff1a;在微信小程序中引用vant组件报错&#xff0c;提示路径不存在&#xff0c;这很有可能是因为没有安装构建vant组件库导致。下面是我整理的安装vant组件库的步骤: 第一步&#xff1a;安装node.js(执行完第一步请重启小程序) 具体步骤请看链接&#xff1a;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&#xff08;26&#xff09; 文章目录 C(Qt)软件调试---内存分析工具Heob&#xff08;26&#xff09;[toc]1、概述&#x1f41c;2、环境配置&#x1fab2;3、功能说明4、使用Heob分析qt 程序内存泄漏&#x1f9a7;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作为一款热门的跨平台开发框架&#xff0c;其UI组件库Material Design深受开发者喜爱。本文将深入探讨Flutter Material Theme的使用&#xff0c;包括如何借助Material Theme Builder创建符合产品需求的主题风格。通过多个场景和代码实例&#xff0c;让你轻松掌握这一工…...

Python 第三方库 PyQt5 的安装

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

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

第7篇:中间件全链路监控与 SQL 性能分析实践

7.1 章节导读 在构建数据库中间件的过程中&#xff0c;可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中&#xff0c;必须做到&#xff1a; &#x1f50d; 追踪每一条 SQL 的生命周期&#xff08;从入口到数据库执行&#xff09;&#…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障

关键领域软件测试的"安全密码"&#xff1a;Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力&#xff0c;从金融交易到交通管控&#xff0c;这些关乎国计民生的关键领域…...

【堆垛策略】设计方法

堆垛策略的设计是积木堆叠系统的核心&#xff0c;直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法&#xff0c;涵盖基础规则、优化算法和容错机制&#xff1a; 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则&#xff1a; 大尺寸/重量积木在下&#xf…...

32单片机——基本定时器

STM32F103有众多的定时器&#xff0c;其中包括2个基本定时器&#xff08;TIM6和TIM7&#xff09;、4个通用定时器&#xff08;TIM2~TIM5&#xff09;、2个高级控制定时器&#xff08;TIM1和TIM8&#xff09;&#xff0c;这些定时器彼此完全独立&#xff0c;不共享任何资源 1、定…...

动态规划-1035.不相交的线-力扣(LeetCode)

一、题目解析 光看题目要求和例图&#xff0c;感觉这题好麻烦&#xff0c;直线不能相交啊&#xff0c;每个数字只属于一条连线啊等等&#xff0c;但我们结合题目所给的信息和例图的内容&#xff0c;这不就是最长公共子序列吗&#xff1f;&#xff0c;我们把最长公共子序列连线起…...

【汇编逆向系列】六、函数调用包含多个参数之多个整型-参数压栈顺序,rcx,rdx,r8,r9寄存器

从本章节开始&#xff0c;进入到函数有多个参数的情况&#xff0c;前面几个章节中介绍了整型和浮点型使用了不同的寄存器在进行函数传参&#xff0c;ECX是整型的第一个参数的寄存器&#xff0c;那么多个参数的情况下函数如何传参&#xff0c;下面展开介绍参数为整型时候的几种情…...

SpringCloud优势

目录 完善的微服务支持 高可用性和容错性 灵活的配置管理 强大的服务网关 分布式追踪能力 丰富的社区生态 易于与其他技术栈集成 完善的微服务支持 Spring Cloud 提供了一整套工具和组件来支持微服务架构的开发,包括服务注册与发现、负载均衡、断路器、配置管理等功能…...

Docker环境下安装 Elasticsearch + IK 分词器 + Pinyin插件 + Kibana(适配7.10.1)

做RAG自己打算使用esmilvus自己开发一个&#xff0c;安装时好像网上没有比较新的安装方法&#xff0c;然后找了个旧的方法对应试试&#xff1a; &#x1f680; 本文将手把手教你在 Docker 环境中部署 Elasticsearch 7.10.1 IK分词器 拼音插件 Kibana&#xff0c;适配中文搜索…...