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

【Gin】Gin框架介绍和使用

一、简单使用Gin框架搭建一个服务器

package mainimport ("github.com/gin-gonic/gin"
)func main() {// 创建一个默认的路由引擎r := gin.Default()// GET 请求方法r.GET("/hello", func(c *gin.Context) {// c.JSON 返回的是JSON格式的数据c.JSON(200, gin.H{"message" : "hello world",})}// 启动HTTP服务器,默认在 0.0.0.0:8080 启动r.Run()
}

       这里,我们只需要记住一下几个函数就可以快速启动一个服务器:还有记住就是一个请求对应一个响应。世界是一个巨大的IO。

gin.Default()  // 创建一个默认的路由引擎GET("/路由", func(c *gin.Context) {}c.JSON(状态码, gin.H{})r.Run() // 启动HTTP服务器

二、RESTful API

       REST 与技术无关,代表的是一种软件架构风格,简单地说,REST的含义就是客户端与服务器之间进行交互的时候,使用HTTP协议中的4种请求方法代表不同的动作。

  • GET用来获取资源
  • POST用来新建资源
  • PUT用来更新资源
  • DELETE用来删除资源

       只要API程序遵循了REST风格,那就可以称其为RESTful API。目前在前后端分离的架构中,前后端基本都是通过RESTful API来进行交互的。

我们可以来看一看下面的代码:

func main() {r := gin.Default()r.GET("/book", func(c *gin.Context) {c.JSON(200, gin.H{"message": "GET",})})r.POST("/book", func(c *gin.Context) {c.JSON(200, gin.H{"message": "POST",})})r.PUT("/book", func(c *gin.Context) {c.JSON(200, gin.H{"message": "PUT",})})r.DELETE("/book", func(c *gin.Context) {c.JSON(200, gin.H{"message": "DELETE",})})
}

三、Gin获取参数

前三个进行获取参数的函数都有三种方法,且函数的格式基本一样:

3.1 获取 querystring 参数

       querystring 指的是 URL中 ? 后面携带的参数:/user/search?username=小王子&address=沙河,获取请求的 querystring 参数的方法如下:

func main() {//Default返回一个默认的路由引擎r := gin.Default()r.GET("/user/search", func(c *gin.Context) {username := c.DefaultQuery("username", "小王子")//username := c.Query("username")address := c.Query("address")//输出json结果给调用方c.JSON(http.StatusOK, gin.H{"message":  "ok","username": username,"address":  address,})})r.Run()
}c.Query()c.DefaultQuery()

       我之前写的一个项目就是需要处理这种URL,不过是在C++上处理,需要将URL获取到,然后进行字符串的切割。

3.2 获取 form 参数

       当前端请求的数据是通过form表单提交的时候,例如向 /user/search 发一个POST请求,获取请求数据的方式如下:

func main() {//Default返回一个默认的路由引擎r := gin.Default()r.POST("/user/search", func(c *gin.Context) {// DefaultPostForm取不到值时会返回指定的默认值//username := c.DefaultPostForm("username", "小王子")username := c.PostForm("username")address := c.PostForm("address")//输出json结果给调用方c.JSON(http.StatusOK, gin.H{"message":  "ok","username": username,"address":  address,})})r.Run(":8080")
}c.PostForm()c.DefaultPostForm()

3.3 获取 JSON 参数

       当前端请求的数据通过JSON提交的时候,例如向 /json 发送一个JSON格式的POST请求,则请求参数的方式如下:

r.POST("/json", func(c *gin.Context) {// 注意:下面为了举例子方便,暂时忽略了错误处理b, _ := c.GetRawData()  // 从c.Request.Body读取请求数据// 定义map或结构体var m map[string]interface{}// 反序列化_ = json.Unmarshal(b, &m)c.JSON(http.StatusOK, m)
})

3.4 获取 path 参数

       请求的参数通过URL路径传递,例如:/user/search/小王子/沙河。获取请求URL路径中的参数的方式如下:

func main() {//Default返回一个默认的路由引擎r := gin.Default()r.GET("/user/search/:username/:address", func(c *gin.Context) {username := c.Param("username")address := c.Param("address")//输出json结果给调用方c.JSON(http.StatusOK, gin.H{"message":  "ok","username": username,"address":  address,})})r.Run(":8080")
}c.Param()c.DefaultParam()

3.5 参数绑定

       为了可以更方便的获取请求相关参数,提高开发效率,我们可以基于请求的 Content-Type 识别请求数据类型并利用反射机制自动提取请求中 QueryString、form 表单、JSON、XML等参数到结构体中,我们可以使用 .ShouldBind() 函数来进行强大的功能,他能够基于请求自动提取 JSON、form表单和QueryString 类型的数据,并把值绑定到指定的结构体对象。

// Binding from JSON
type Login struct {User     string `form:"user" json:"user" binding:"required"`Password string `form:"password" json:"password" binding:"required"`
}func main() {router := gin.Default()// 绑定JSON的示例 ({"user": "q1mi", "password": "123456"})router.POST("/loginJSON", func(c *gin.Context) {var login Loginif err := c.ShouldBind(&login); err == nil {fmt.Printf("login info:%#v\n", login)c.JSON(http.StatusOK, gin.H{"user":     login.User,"password": login.Password,})} else {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})}})// 绑定form表单示例 (user=q1mi&password=123456)router.POST("/loginForm", func(c *gin.Context) {var login Login// ShouldBind()会根据请求的Content-Type自行选择绑定器if err := c.ShouldBind(&login); err == nil {c.JSON(http.StatusOK, gin.H{"user":     login.User,"password": login.Password,})} else {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})}})// 绑定QueryString示例 (/loginQuery?user=q1mi&password=123456)router.GET("/loginForm", func(c *gin.Context) {var login Login// ShouldBind()会根据请求的Content-Type自行选择绑定器if err := c.ShouldBind(&login); err == nil {c.JSON(http.StatusOK, gin.H{"user":     login.User,"password": login.Password,})} else {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})}})// Listen and serve on 0.0.0.0:8080router.Run(":8080")
}

ShouldBind 会按照下面的顺序解析请求中的数据进行绑定:

  1. 如果是 GET 请求,只使用 Form 绑定引擎(query)。
  2. 如果是 POST 请求,首先检查 content-type 是否为 JSON 或 XML,然后再使用Form(form-data)

四、文件上传

4.1 单个文件上传

文件上传前端页面代码:

<!DOCTYPE html>
<html lang="zh-CN">
<head><title>上传文件示例</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data"><input type="file" name="f1"><input type="submit" value="上传">
</form>
</body>
</html>

后端 gin 框架部分代码:

func main() {router := gin.Default()// 处理multipart forms提交文件时默认的内存限制是32 MiB// 可以通过下面的方式修改// router.MaxMultipartMemory = 8 << 20  // 8 MiBrouter.POST("/upload", func(c *gin.Context) {// 单个文件file, err := c.FormFile("f1")if err != nil {c.JSON(http.StatusInternalServerError, gin.H{"message": err.Error(),})return}log.Println(file.Filename)dst := fmt.Sprintf("C:/tmp/%s", file.Filename)// 上传文件到指定的目录c.SaveUploadedFile(file, dst)c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("'%s' uploaded!", file.Filename),})})router.Run()
}

4.2 多个文件上传

五、重定向

5.1 HTTP重定向

r.GET("/test", func(c *gin.Context) {c.Redirect(http.StatusMovedPermanently, "http://www.sogo.com/")
})

5.2 路由重定向

r.GET("/test", func(c *gin.Context) {// 指定重定向的URLc.Request.URL.Path = "/test2"r.HandleContext(c)
})
r.GET("/test2", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"hello": "world"})
})

六、Gin路由

6.1 普通路由

6.2 路由组

七、Gin中间件

       我感觉这个中间件有点像C++回调函数。Gin框架允许开发者在处理请求的过程中,加入用户自己的钩子(Hook)函数。这个钩子函数就叫中间件,中间件适合处理一些公共的业务逻辑,比如登录认证、权限校验、数据分页、记录日志、耗时统计等。

7.1 定义中间件

Gin中的中间件必须是一个 gin.HandlerFunc 类型的。

// StatCost 是一个统计耗时请求耗时的中间件
func StatCost() gin.HandlerFunc {return func(c *gin.Context) {start := time.Now()c.Set("name", "小王子") // 可以通过c.Set在请求上下文中设置值,后续的处理函数能够取到该值// 调用该请求的剩余处理程序c.Next()// 不调用该请求的剩余处理程序// c.Abort()// 计算耗时cost := time.Since(start)log.Println(cost)}
}

7.2 注册中间件

func main() {// 新建一个没有任何默认中间件的路由r := gin.New()// 注册一个全局中间件r.Use(StatCost())r.GET("/test", func(c *gin.Context) {name := c.MustGet("name").(string) // 从上下文取值log.Println(name)c.JSON(http.StatusOK, gin.H{"message": "Hello world!",})})r.Run()
}
// 给/test2路由单独注册中间件(可注册多个)r.GET("/test2", StatCost(), func(c *gin.Context) {name := c.MustGet("name").(string) // 从上下文取值log.Println(name)c.JSON(http.StatusOK, gin.H{"message": "Hello world!",})})
shopGroup := r.Group("/shop", StatCost())
{shopGroup.GET("/index", func(c *gin.Context) {...})...
}shopGroup := r.Group("/shop")
shopGroup.Use(StatCost())
{shopGroup.GET("/index", func(c *gin.Context) {...})...
}

7.3 中间件注意事项

7.3.1 gin 默认中间件

gin.Default()默认使用了LoggerRecovery中间件,其中:

  • Logger中间件将日志写入gin.DefaultWriter,即使配置了GIN_MODE=release
  • Recovery中间件会recover任何panic。如果有panic的话,会写入500响应码。

如果不想使用上面两个默认的中间件,可以使用gin.New()新建一个没有任何默认中间件的路由

7.3.2 gin 中间件中使用 goroutine 

       当在中间件或handler中启动新的goroutine时,不能使用原始的上下文(c *gin.Context),必须使用其只读副本(c.Copy())。

相关文章:

【Gin】Gin框架介绍和使用

一、简单使用Gin框架搭建一个服务器 package mainimport ("github.com/gin-gonic/gin" )func main() {// 创建一个默认的路由引擎r : gin.Default()// GET 请求方法r.GET("/hello", func(c *gin.Context) {// c.JSON 返回的是JSON格式的数据c.JSON(200, g…...

AI大模型带来哪些创业机遇?

AI 大模型的快速发展带来了许多创新和创业机遇&#xff0c;涵盖了从行业应用到基础设施优化的方方面面。以下是一些具体的创业机会&#xff1a; 1、垂直行业应用 大模型可以根据不同行业的需求进行定制和优化&#xff0c;提供高度专业化的 AI 解决方案。 医疗领域&#xff1a;…...

[Linux] 层层深入理解文件系统——(3)磁盘组织存储的文件

标题&#xff1a;[Linux] 层层深入理解文件系统——&#xff08;3&#xff09;磁盘组织组织存储的文件 个人主页水墨不写bug 目录 一、磁盘中的文件 1&#xff09;磁盘的物理结构 2&#xff09;磁盘的CHS寻址法 3&#xff09;磁盘的空间管理 二、磁盘如何组织存储文件 三…...

Apache Cordova学习计划

Apache Cordova&#xff08;之前称为 PhoneGap&#xff09;&#xff1a; 1. PhoneGap的起源&#xff1a;2008年8月&#xff0c;PhoneGap在旧金山的iPhoneDevCamp上首次亮相&#xff0c;由Nitobe公司开发&#xff0c;目的是“为跨越Web技术和iPhone之间的鸿沟牵线搭桥”。 2. Ph…...

Unity学习日志-API

Untiy基本API 角度旋转自转相对于某一个轴 转多少度相对于某一个点转练习 角度 this.transform.rotation(四元数)界面上的xyz(相对于世界坐标) this.transform.eulerAngles;相对于父对象 this.transform.localEulerAngles;设置角度和设置位置一样&#xff0c;不能单独设置xz…...

Java基础常见面试题总结(上)

基础概念与常识 Java 语言有哪些特点? 简单易学&#xff08;语法简单&#xff0c;上手容易&#xff09;&#xff1b;面向对象&#xff08;封装&#xff0c;继承&#xff0c;多态&#xff09;&#xff1b;平台无关性&#xff08; Java 虚拟机实现平台无关性&#xff09;&…...

4 -《本地部署开源大模型》在Ubuntu 22.04系统下部署运行ChatGLM3-6B模型

在Ubuntu 22.04系统下部署运行ChatGLM3-6B模型 大模型部署整体来看并不复杂&#xff0c;且官方一般都会提供标准的模型部署流程&#xff0c;但很多人在部署过程中会遇到各种各样的问题&#xff0c;很难成功部署&#xff0c;主要是因为这个过程会涉及非常多依赖库的安装和更新及…...

本地如何使用Pycharm连接远程服务器调试torchrun

pycharm 远程连接服务器并且debug, 支持torch.distributed.launch debug_pycharm远程debug-CSDN博客 上面这个博客写的真的非常好&#xff0c;记录一下&#xff0c;需要注意该博主的主机为mac 本人可调试版本为&#xff1a; 可直接运行版本为&#xff1a;...

Visual Studio 2022常用快捷键

1. 基本编辑快捷键 Ctrl X&#xff1a;剪切选中内容Ctrl C&#xff1a;复制选中内容Ctrl V&#xff1a;粘贴内容Ctrl Z&#xff1a;撤销Ctrl Y&#xff1a;重做Ctrl Shift L&#xff1a;删除当前行Ctrl K, Ctrl C&#xff1a;注释选中的代码Ctrl K, Ctrl U&#xf…...

mysql innodb 引擎如何直接复制数据库文件?

mysql innodb 引擎如何直接复制数据库文件&#xff1f;介绍如下&#xff1a; 1、首先找到数据库文件所在位置 一般可以看my.conf/my.ini配置的文件的“datadir” 看示例&#xff1a; “MAMP”在Macos下的数据库文件位置&#xff1a; /Library/Application Support/appsolu…...

python中的global和nonlocal关键字以及闭包和模块

global i 这样的用法在于 Python 中&#xff0c;但需要在一个函数内部使用&#xff0c;以便将变量 i 声明为全局变量。让我们来详细讲解一下它的用法。 什么是全局变量&#xff1f; 全局变量是指在函数外部定义的变量&#xff0c;可以在任何函数中访问和修改。如果你需要在函数…...

LabVIEW风机滚动轴承监测系统

矿井主通风机作为矿井中最重要的通风设备&#xff0c;一旦出现故障&#xff0c;不仅会影响矿井内的空气质量&#xff0c;还可能引发安全事故。研究表明&#xff0c;通风机中约30%的故障是由轴承问题引起的。因此&#xff0c;能够实时监控矿井主通风机轴承状态的系统&#xff0c…...

第1节 什么是鸿蒙系统

鸿蒙系统&#xff08;HarmonyOS&#xff09;是华为公司发布的一款基于微内核的面向全场景的分布式操作系统。以下是对它的具体介绍&#xff1a; 1. 核心特点&#xff1a; • 分布式能力&#xff1a;这是鸿蒙系统的核心优势之一。它能够将多种不同类型的智能终端设备连接起来&a…...

CentOS 7 将 YUM 源更改为国内镜像源

在 CentOS 7 中&#xff0c;将 YUM 源更改为国内的阿里云镜像源可以提高软件包的下载速度。以下是具体的步骤&#xff1a; 1. 备份原有 YUM 源配置 首先&#xff0c;建议你备份当前的 YUM 源配置&#xff0c;以防后续需要恢复&#xff1a; sudo cp -r /etc/yum.repos.d /etc…...

python调用dircmp进行文件夹比较

不同电脑上的同一部署文件&#xff0c;由于更新频率不相同导致两边内容有差异&#xff0c;需要比较两边的文件夹及文件差异。之前写过批量修改文件名的Python代码&#xff0c;因此优先想用python处理。   百度“python 文件夹对比”&#xff0c;不少文章都是自己实现的文件夹…...

微信小程序 - 供应链系统设计

文章目录 一、系统概述二、系统架构设计三、系统安全设计四、系统性能优化五、系统部署与维护 在当今数字化时代&#xff0c;供应链管理对于企业的高效运营至关重要。微信小程序作为一种便捷的移动应用形式&#xff0c;为供应链系统的开发提供了新的机遇。本文将从系统架构设计…...

嵌入式学习-IO进程-Day03

嵌入式学习-IO进程-Day03 IO进程 获取文件属性&#xff08;stat&#xff09; 库 库的概念 库的分类 静态库的制作 动态库的制作 进程 进程和程序的区别 进程的特点 进程三段 进程的类型 进程的运行状态 进程状态转换图&#xff08;重点&#xff09; 进程的函数接口 创建进程for…...

docker安装elasticsearch和ik分词器

目录 ElasticSearch 了解ElasticSearch ELK技术栈 ​编辑 ElasticSearch与lucene的关系 总结 倒排索引 正向索引 倒排索引 正向和倒排 elasticSearch特定的一些概念 文档和字段 索引和映射 mysql与elasticsearch对比 安装elasticSeacher并部署单例es 创建网络 加…...

|智能门票|008_django基于Python的智能门票设计与实现2024_i16z2v70

目录 系统展示 设计步骤 代码实现 项目案例 获取源码 博主介绍&#xff1a;CodeMentor毕业设计领航者、全网关注者30W群落&#xff0c;InfoQ特邀专栏作家、技术博客领航者、InfoQ新星培育计划导师、Web开发领域杰出贡献者&#xff0c;博客领航之星、开发者头条/腾讯云/AW…...

QFramework v1.0 使用指南 更新篇:20240919. 新增 BindableDictionary

增加了三个比较常用的屏幕过渡&#xff1a;FadeIn&#xff0c;FadeOut&#xff0c;FadeInOut。 示例代码如下: using UnityEngine;namespace QFramework.Example {public class ScreenTransitionsExample : MonoBehaviour{private void OnGUI(){IMGUIHelper.SetDesignResolut…...

vue实现文件预览和文件上传、下载、预览——多图、模型、dwg图纸、文档(word、excel、ppt、pdf)

整体思路&#xff08;模型特殊不考虑&#xff0c;别人封装不具备参考性&#xff09; 图片上传采用单独的组件&#xff0c;其他三种类型采用一个上传组件&#xff08;仅仅文件格式不同&#xff09;文件上传采用前端直接上传阿里云的方式图片预览使用elementUI自带的image预览dw…...

探讨人工智能领域所需学习的高等数学知识及其应用场景,涵盖了微积分、线性代数、概率论等多个数学分支。

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下本文主要探讨了人工智能领域所需学习的高等数学知识及其应用场景。文章详细列出了人工智能中涉及的数学公式&#xff0c;涵盖了微积分、线性代数、概率论等多个数学分支。同时&#xff0c;本文深入介绍了这些数学知…...

详解安卓和IOS的唤起APP的机制,包括第三方平台的唤起方法比如微信

网页唤起APP是一种常见的跨平台交互方式&#xff0c;它允许用户从网页直接跳转到移动应用程序。 这种技术广泛应用于各种场景&#xff0c;比如让用户在浏览器中点击链接后直接打开某个应用&#xff0c;或者从网页引导用户下载安装应用。实现这一功能主要依赖于URL Scheme、Univ…...

服务器数据恢复—raid5阵列中多块硬盘离线导致崩溃的数据恢复案例

服务器数据恢复环境&#xff1a; 三台V7000存储&#xff0c;共有64块SAS硬盘&#xff08;其中有三块热备盘&#xff0c;其中一块已启用&#xff09;组建了数组raid5阵列。分配若干LUN&#xff0c;上层安装Windows server操作系统&#xff0c;数据分区格式化为NTFS文件系统。 服…...

《深度学习》OpenCV FisherFaces算法人脸识别 原理及案例解析

目录 一、FisherFaces算法 1、什么是FisherFaces算法 2、原理 3、特点 4、算法步骤 1&#xff09;数据预处理 2&#xff09;特征提取 3&#xff09;LDA降维 4&#xff09;特征投影 5&#xff09;人脸识别 二、案例解析 1、完整代码 运行结果&#xff1a; 一、Fish…...

基于Python+Flask的天气预报数据可视化分析系统(源码+文档)

简介&#xff1a; 本系统是一个集数据收集、处理、分析和可视化于一体的天气预报数据平台。通过Python和Flask框架的结合&#xff0c;我们能够高效地构建出一个用户友好的Web界面&#xff0c;让用户能够轻松访问并理解复杂的天气数据。系统不仅能够实时获取最新的天气信息&…...

深入解析 Flutter兼容鸿蒙next全体生态的横竖屏适配与多屏协作兼容架构

目录 写在前面 1. Flutter 的基本适配机制 1.1 响应式布局 1.2 逻辑像素 2. 横屏与竖屏的适配 2.1 方向感知 2.2 针对方向的布局优化 3. 多屏协作的实现 3.1 适配多屏显示 3.2 使用 StreamBuilder 和 Provider 3.3 多设备协作的挑战 4. 实践中的应用场景 4.1 移动办…...

【Spring】Spring实现加法计算器和用户登录

加法计算器 准备工作 创建 SpringBoot 项目&#xff1a;引入 Spring Web 依赖&#xff0c;把前端的页面放入项目中 **<!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport"…...

电脑d盘不见了怎么恢复?

在使用电脑的时候&#xff0c;我们可能会遇到这样一个问题&#xff0c;电脑里的D盘突然不见了&#xff0c;在“此电脑”中看不到D盘了。这这个情况可能会让人感到非常困惑甚至是头疼&#xff0c;因为D盘里面可能存放着非常重要的文件。今天的内容要和大家分析一下D盘不见的原因…...

电子商务网站维护技巧:保持WordPress、主题和插件的更新

在这个快节奏的数字时代&#xff0c;维护一个电子商务网站的首要任务之一是保持WordPress、主题和插件的最新状态。过时的软件不仅可能导致功能故障&#xff0c;还可能带来安全风险。本文将深入探讨如何有效地更新和维护您的WordPress网站&#xff0c;以确保其安全性和性能。 …...