GO语言 gin框架 简述

原文地址 基本路由 · Go语言中文文档

一、简介

    Gin是一个golang的轻量级web框架,性能不错,API友好。

    Gin支持Restful风格的API,可以直接从URL路径上接收api参数或者URL参数,也可是使用json或者表单 数据绑定的方式接收参数。

    Gin响应前端的方式,可以使用的方式包括 json、结构体、protobuff的、XML、YAML。

    Gin可以使用路由分组的方式管理API,支持api路径重定向

    Gin的路由库用的是 httprouter,路由节点的数据结构是压缩字典树,提高路由效率。

    Gin支持全局中间件和局部中间件,支持中间件分段逻辑的Next方法

    Gin支持cookie和Session的方法去识别和验证客户端。

    Gin支持 Air 实时监听代码文件自动重新编译执行。

二、gin路由

1. 基本路由

    gin 框架中采用的路由库是基于 httprouter 做的,是第三方HTTP路由包,特点高性能、可扩展

(1) 使用方式:

     New()函数生成了一个 Router对象 。

     GET()方法 或 POST()方法 注册一个适配路径的响应函数  

     将 Router对象 作为参数传给 ListenAndServe()函数 启动HTTP服务。

router := httprouter.New()
router.GET("/", handleFunc)
http.ListenAndServe(":8080", router)

(2) httprouter 为常用的HTTP方法提供快捷使用方式:

     获取:  func (r *Router) GET(path string, handle Handle)

     添加:  func (r *Router) POST(path string, handle Handle)

     修改:  func (r *Router) PUT(path string, handle Handle)

     删除:  func (r *Router) DELETE(path string, handle Handle)

(3) httprouter 包中对URL使用两种匹配模式:

     形如/user/name的精确匹配

     形如/user/*name的匹配所有的模式

(4) 可以处理二级域名。先 根据域名获取对应的Handler路由,然后调用分发机制去处理。

func main() {......//分别处理不同的二级域名hs := make(HostMap)hs["sub1.localhost:8080"] = userRouterhs["sub2.localhost:8080"] = dataRouter//一级域名:localhost,二级域名:sub1.localhosthttp.ListenAndServe(":8080", hs)
}type HostMap map[string]http.Handlerfunc (hs HostMap) ServeHTTP(w http.ResponseWriter, r *http.Request) {//先根据域名获取对应的Handler路由,然后调用处理if handler := hs[r.Host]; handler != nil {handler.ServeHTTP(w, r)}
}
2. Restful风格的API

    gin支持Restful风格的API,即: URL定位资源,用HTTP描述操作。例如:

(1) 获取文章 /blog/getXxx Get blog/Xxx

(2) 添加 /blog/addXxx POST blog/Xxx

(3) 修改 /blog/updateXxx PUT blog/Xxx

(4) 删除 /blog/delXxxx DELETE blog/Xxx

3. API参数

    Api参数就是在Api地址上输入的参数。

    可以通过Context的Param方法来获取API参数

func main() {r := gin.Default()r.GET("/user/:name/*action", func(c *gin.Context) {name := c.Param("name")action := c.Param("action")action = strings.Trim(action, "/") //截取/后面的内容c.String(http.StatusOK, name+" is "+action)})r.Run(":8000") //监听8080端口
}

 在浏览器输入:   http://localhost:8080/user/枯藤/doview,获得name参数"枯藤",action参数 "doview"

4. URL参数

   URL参数就是在用Get方式,在?后面输入的参数。

   可以通过DefaultQuery()或Query()方法获取URL参数

r.GET("/user", func(c *gin.Context) {name := c.DefaultQuery("name", "枯藤")    //name是参数名称,枯藤是默认值c.String(http.StatusOK, fmt.Sprintf("hello %s", name))
})

 在浏览器输入:   http://localhost:8080/user?name=乌鸦,获得name参数"乌鸦"

5. 表单参数

(1) 表单传输为 post请求。http常见的传输格式:

    application/json

    application/x-www-form-urlencoded (默认)

    multipart/form-data

(2) 表单参数可以通过 PostForm() 方法获取

r.POST("/form", func(c *gin.Context) {username := c.PostForm("username")password := c.PostForm("userpassword")c.String(http.StatusOK, fmt.Sprintf("username:%s,password:%s", username, password))
})
6. 上传单个文件

(1) multipart/form-data格式用于文件上传

(2) 通过 FormFile() 方法获得文件对象 

r.POST("/upload", func(c *gin.Context) {file, err := c.FormFile("file")c.String(http.StatusOK, file.Filename)})
7. 上传多个文件

(1) 上传多个文件也是用 multipart/form-data格式

(2) 通过 MultipartForm() 方法获得文件对象列表

r.POST("/upload", func(c *gin.Context) {form, err := c.MultipartForm()files := form.File["files"]    // 获取所有图片for _, file := range files {    // 遍历所有图片c.SaveUploadedFile(file, file.Filename)}
})
8. routes group

  routes group(路由分组) 可以分组管理相同的URL。 

   如下代码,v1和v2分别是两个路由组。

func main() {r := gin.Default() //创建默认路由v1 := r.Group("/v1")    //路由组1{   // {} 是书写规范v1.GET("/login", login)v1.GET("submit", submit)}v2 := r.Group("/v2")    //路由组2{v2.POST("/login", login)v2.POST("/submit", submit)}r.Run(":8000")
}
9. 路由原理

  httprouter使用的数据结构是压缩字典树。

  普通的字典树:每个字母都建立一个路由节点

  压缩字典树:只对每个有效前缀建立路由节点。如下图所示:

三、gin数据解析和绑定

     支持三种方式的数据解析,json、表单 和 url参数

1. Json 数据解析和绑定

     使用 context 的 ShouldBindJSON 方法

type Login struct {User    string `json:"user"  binding:"required"`Pssword string `json:"password"  binding:"required"`
}func main() {r := gin.Default()r.POST("loginJSON", func(c *gin.Context) {// 声明接收的变量var json Login// 将request的body中的数据,自动按照json格式解析到结构体if err := c.ShouldBindJSON(&json); err != nil {......}......})......
}
2. 表单数据解析和绑定

   使用 context 的 Bind 方法

type Login struct {User    string `form:"username" binding:"required"`Pssword string `form:"password" binding:"required"`
}func main() {r := gin.Default()r.POST("/loginForm", func(c *gin.Context) {var form Login// Bind()默认解析并绑定form格式// 根据请求头中content-type自动推断if err := c.Bind(&form); err != nil {......}......})......
}
3. URI数据解析和绑定

   使用 context 的 ShouldBindUri 方法

type Login struct {User    string `uri:"user" xml:"user" binding:"required"`Pssword string `uri:"password" xml:"password" binding:"required"`
}func main() {r := gin.Default()r.GET("/:user/:password", func(c *gin.Context) {if err := c.ShouldBindUri(&login); err != nil {.......}.......}).......
}

四、gin 渲染

1. 各种数据格式的响应

(1) json 响应

c.JSON(200, gin.H{"message": "someJSON", "status": 200})

(2) 结构体 响应

var msg struct {Name    stringMessage string
}
msg.Name = "root"
msg.Message = "message"
c.JSON(200, msg)

(3) XML,YAML 响应

c.XML(200, gin.H{"message": "abc"})
c.YAML(200, gin.H{"name": "zhangsan"})

(4) protobuf 响应

data := &protoexample.Test{Label: &label,Reps:  reps,
}
c.ProtoBuf(200, data)
2. HTML模板渲染

   gin支持加载 HTML模板, 然后根据模板参数进行配置并返回相应的数据。

   本质上就是字符串替换。

func main() {r := gin.Default()r.LoadHTMLGlob("tem/*")    //加载模板文件r.GET("/index", func(c *gin.Context) {//index.html就是具体的模板文件c.HTML(http.StatusOK, "index.html", gin.H{"title": "我是测试", "ce": "123456"})})r.Run()
}
3. 重定向

  可以使用 context 的  Redirect 方法进行重定向

func main() {r := gin.Default()r.GET("/redirect_me", func(c *gin.Context) {c.Redirect(http.StatusMovedPermanently, "http://www.5lmh.com")})r.Run()
}

  当客户端请求 /redirect_me 时,服务器将重定向到 https://www.5lmh.com

4. 同步异步

  goroutine机制可以实现异步处理,但不应该使用原始上下文,必须使用它的只读副本。

func main() {r := gin.Default()r.GET("/long_async", func(c *gin.Context) { copyContext := c.Copy()    // 需要拷贝一个副本go func() {    // 异步处理time.Sleep(3 * time.Second)log.Println("异步执行:" + copyContext.Request.URL.Path)}()})r.Run(":8000")
}

五、gin中间件

1. 全局中间件

    所有请求都经过此中间件。

    实现代码如下:

func MiddleWare() gin.HandlerFunc {......
}func main() {r := gin.Default()r.Use(MiddleWare())r.Run()
}
2. Next()方法

    当程序执行到context.Next时,会转而先去执行具体的业务逻辑。

    执行完业务逻辑处理函数之后,程序会再次回到context.Next处,继续执行中间件后续的代码。

func MiddleWare() gin.HandlerFunc {return func(c *gin.Context) {fmt.Println("中间件开始执行了")c.Next()    //转去执行业务逻辑//业务逻辑执行完,返回此处,继续执行中间件代码.......fmt.Println("中间件执行完毕", status)}
}func main() {r := gin.Default()r.Use(MiddleWare())    // 注册中间件r.GET("/ce", func(c *gin.Context) {......})r.Run()
}

  解释原文 Golang gin 中间件、context.Next函数_gin context.next-CSDN博客

3. 局部中间件

    中间件只在具体某个路由生效,不使用 r.use() 定义的中间件。

func main() {r := gin.Default()//只在 /ce 的路由里使用局部中间件 PartMiddleWare()r.GET("/ce", PartMiddleWare(), func(c *gin.Context) { ......})r.Run()
}

  解释原文 局部生效的中间件_如何使用局部中间件-CSDN博客

六、会话控制

 1. Cookie介绍

(1) HTTP是无状态协议,服务器不能记录浏览器的访问状态,不能区分两次请求是否由同一个客户端发出。

(2) Cookie 就是一段可以区分不同客户端的信息,由服务器创建,发送给浏览器,浏览器保存。

(3) 浏览器向服务器发送请求时,都会同时将Cookie发送给服务器,服务器根据处理请求。

2. Cookie的使用

   登录时设置cookie,其他请求检验cookie,代码如下:

func AuthMiddleWare() gin.HandlerFunc {return func(c *gin.Context) {//2.获取cookie并校验if cookie, err := c.Cookie("abc"); err == nil {if cookie == "123" {c.Next() //3.cookie检验通过,执行请求逻辑return}}......return}
}func main() {r := gin.Default()r.GET("/login", func(c *gin.Context) {c.SetCookie("abc", "123", 60, "/", "localhost", false, true) //1.登录成功,设置cookiec.String(200, "Login success!")})......
}
3. Cookie的缺点

(1) 不安全,明文,容易泄露信息

(2) 可以被浏览器禁用。

(3) 有数量限制。某些浏览器对某个域名的cookie有数量限制,大概50个。

4. Sessions

(1) session和cookie 实现的目标是一致的,但实现的方法不同;

(2) session 是另一种记录客户状态的机制, 不同的是 Cookie 保存在客户端浏览器中,而 session保存在服务器

(3) 浏览器第一次访问服务器时,服务器端会创建一个 session 对象,生成一个类似于 key,value 的键值对, 然后将 value 保存到服务器,将 key(cookie)返回到浏览器(客户)端。
      浏览器下次访问时会携带 key(cookie),找到对应的 session(value)。

(4) sessions包地址: github.com/gorilla/sessions

七、参数验证

1. 结构体验证

   用gin框架的数据验证,可以不用解析数据,减少if else,会简洁许多。

   比如,在定义结构体时,添加如下 binding:"required,gt=10",表示不能为空并且大于10

type Person struct {//不能为空并且大于10Age      int       `form:"age" binding:"required,gt=10"`
}
 2. 自定义验证

    可以自定义验证函数,并注册到 validator中。

    包地址:gopkg.in/go-playground/validator.v9/translations

type Person struct {//1.在binding上使用自定义的 参数名称 stringCheckNameName    string `form:"name" binding:"stringCheckName"`
}
//2.自定义的校验方法
func checkStringValid(v *validator.Validate, ......) bool {if value, ok := field.Interface().(string); ok {return value != "" && !("5lmh" == value) //字段不能为空,并且不等于5lmh}return true
}
func main() {r := gin.Default()// 3、将我们自定义的校验方法 和 参数名称 注册到 validator中if v, ok := binding.Validator.Engine().(*validator.Validate); ok {v.RegisterValidation("stringCheckName", checkStringValid)}
}
3. 多语言翻译验证

   如需要自定义返回信息的语言,比如部分用户返回中文,部分返回英文。

   可以使用  validator.v9/translations

import (ut "github.com/go-playground/universal-translator"en_translations "gopkg.in/go-playground/validator.v9/translations/en"
)
func startPage(c *gin.Context) {locale := c.DefaultQuery("locale", "zh")  //1.获得前端使用语言//2.获得翻译器en := en.New()zh := zh.New()Uni = ut.New(en, zh)trans, _ := Uni.GetTranslator(locale)     //3.注册翻译器Validate = validator.New()en_translations.RegisterDefaultTranslations(Validate, trans) //4.解析结构体,获得翻译过的内容user := User{}c.ShouldBind(&user)err := Validate.Struct(user)
}

八、其他

1. 日志

  使用 io.MultiWriter  和 gin.DefaultWriter

import ("io""os"
)
func main() {f, _ := os.Create("gin.log")gin.DefaultWriter = io.MultiWriter(f) //将日志写入文件//gin.DefaultWriter = io.MultiWriter(f, os.Stdout) //将日志同时写入文件和控制台
}
2. Air 实时加载

    在开发调试的时候,变更代码之后需要按下Ctrl+C停止程序并重新编译再执行,不是很方便。

    Air能够实时监听项目的代码文件,在代码发生变更之后自动重新编译并执行,提高开发效率。

3. gin验证码

   为了防止接口被恶意频繁调用,可以采用加验证码的方式。

   库地址:github.com/dchest/captcha

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

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

相关文章

【传知代码】BERT论文解读及情感分类实战-论文复现

文章目录 概述原理介绍BERT模型架构任务1 Masked LM(MLM)任务2 Next Sentence Prediction (NSP)模型输入下游任务微调GLUE数据集SQuAD v1.1 和 v2.0NER 情感分类实战IMDB影评情感数据集数据集构建模型构建 核心代码超参数设置训练结果注意事项 小结 本文…

AIOps在线评测基准首阶段建设完成,面向社区发布真实运维数据!

本文根据必示科技算法研究员、产品总监聂晓辉博士在2024 CCF国际AIOps挑战赛线下宣讲会上的演讲整理成文。 2024年1月份OpenAIOps社区成立,随着越来越多的社区成员加入,各项工作在有条不紊的推进中。在线评测基准系统(AIOps Live Benchmark&a…

积鼎CFDPro水文水动力模型,专为中小流域洪水“四预”研发的流体仿真技术

水动力模型与水文模型是水利工程与水文学研究中不可或缺的两大工具。水动力模型着重于流体运动的动力学机制,通过一系列方程组捕捉水流的时空变化,而概念性水文模型则侧重于流域尺度的水文循环过程,利用物理概念与经验关系进行近似模拟。两者…

Windows系统部署YOLOv5 v6.1版本的训练与推理环境保姆级教程

文章目录 一 概述二 依赖环境(prerequisites)2.1 硬件环境2.2 软件环境 三 环境安装3.1 创建并激活虚拟环境3.2 安装Pytorch与torchvision3.3 校验Pytorch安装3.4 下载 YOLOv5 v6.1 源码3.5 安装 YOLOv5 依赖3.6 下载预训练模型3.7 安装其他依赖3.8 测试环境安装3.9 测试训练流…

jupyter notebook更改位置

1.找到jupyer的配置文件 一般在c盘用户的.jupter文件夹下 2. 用记事本打开这个配置文件,定位到c.NotebookApp.notebook_dir /path_to_your_directory 替换你的位置 3.找到jupyer图标的位置,打开属性 添加要存放的位置在目标文件的末尾,重新…

一个全面了解Xilinx FPGA IP核的窗口:《Xilinx系列FPGA芯片IP核详解》(可下载)

随着摩尔定律的逐渐放缓,传统的芯片设计方法面临着越来越多的挑战。而FPGA以其并行处理能力和可编程性,为解决复杂问题提供了新的途径。它允许设计者在同一个芯片上实现多种不同的功能模块,极大地提高了资源的利用率和系统的综合性能。 FPGA…

HCIA-ARP

ARP的由来 ARP这一种协议它会是在我们HCIA中第一个需要完全掌握的一个协议,不然对于数据通讯来说大家都会一直觉得很绕圈 协议栈,网线,网卡,它们组成了我们最小的数据通信的小脉络注:可以了解ARP攻击(冒充访…

文献解读-群体基因组第二期|《中国人群中PAX2新生突变的检测及表型分析:一项单中心研究》

关键词:应用遗传流行病学;群体测序;群体基因组;基因组变异检测; 文献简介 标题(英文):Detection of De Novo PAX2 Variants and Phenotypes in Chinese Population: A Single-Cente…

new CCDIKSolver( OOI.kira, iks ); // 创建逆运动学求解器

demo案例 new CCDIKSolver(OOI.kira, iks); 在使用某个特定的库或框架来创建一个逆运动学(Inverse Kinematics, IK)求解器实例。逆运动学在机器人学、动画和计算机图形学等领域中非常重要,它用于根据期望的末端执行器(如机器人的…

建设现代智能工业-智能化、数字化、自动化节能减排

建设现代智能工业-智能化节能减排 遵循“一体化”能源管理(Integrated Energy Management)的设计宗旨,集成城市各领域(如工业.交通、建筑等)的能源生产和消费信息,面向城市政府、企业、公众三类实体,提供“一体化”的综合能源管理…

uniapp h5项目切换导航栏及动态渲染按钮颜色

1.效果图 2.html,动态渲染按钮样式---三元判断 <!-- 切换栏 --><view class"statusList"><block v-for"(item,index) in list" :key"index"><view class"swiper-tab-list" :class"current item.id?activ…

CEEMDAN +组合预测模型(CNN-Transfromer + XGBoost)

注意&#xff1a;本模型继续加入 组合预测模型全家桶 中&#xff0c;之前购买的同学请及时更新下载! 往期精彩内容&#xff1a; 时序预测&#xff1a;LSTM、ARIMA、Holt-Winters、SARIMA模型的分析与比较-CSDN博客 VMD CEEMDAN 二次分解&#xff0c;Transformer-BiGRU预测模…

【JAVA WEB实用与优化技巧】如何自己封装一个自定义UI的Swagger组件,包含Swagger如何处理JWT无状态鉴权自动TOKEN获取

目录 一、Swagger 简介1. 什么是 Swagger&#xff1f;2. 如何使用 Swagger3. Springboot 中swagger的使用示例1. maven 引入安装2. java配置 二、Swagger UI存在的缺点1.不够方便直观2.请求的参数没有缓存3.不够美观4.如果是JWT 无状态登录&#xff0c;Swagger使用起来就没有那…

STL-stack的使用及其模拟实现

在C标准库中&#xff0c;stack是一种容器适配器&#xff0c;它以后进先出的方式组织数据&#xff0c;其删除只能从容器的栈顶进行元素的插入与取出操作。 stack的使用 stack的构造函数 stack的成员函数 empty&#xff1a;判断栈是否为空back&#xff1a;返回当前栈中元素的数量…

推荐一个 Java 开源企业级新能源汽车智能共享充电桩管理平台

文末可获取 Orise 平台源码 01 Orise 智能充电桩管理平台 奥升( Orise ) 新能源汽车充电桩管理 Saas 云平台是一个集充电设备管理、用户充电管理、线上小程序内容管理于一体的综合管理平台。Orise充电桩平台支持高并发业务、业务动态伸缩、桩通信负载均衡&#xff0c;通过Docke…

Golang项目代码组织架构实践

Golang在项目结构上没有强制性规范&#xff0c;虽然这给了开发者很大的自由度&#xff0c;但也需要自己沉淀一套可行的架构。本文介绍了一种项目布局&#xff0c;可以以此为参考设计适合自己的 Golang 项目组织模式。原文: Golang Project Layout Go 有很多强制的或是约定俗成的…

收藏:六款好用的企业防泄密软件推荐

企业数据如同企业的生命线&#xff0c;保护数据安全免遭泄露变得至关重要。 面对日益复杂的网络安全威胁&#xff0c;一套高效的企业防泄密软件成为企业安全架构的基石。 以下是精心挑选的六款企业防泄密软件&#xff0c;它们在数据加密、访问控制、行为监控等方面表现出色&am…

lua vm 常识一: attempt to yield across a C-call boundary 的原因分析

使用 lua 的时候有时候会遇到这样的报错&#xff1a;“attempt to yield across a C-call boundary”。 1. 网络上的解释 可以在网上找到一些关于这个问题的解释。 1.1 解释一 这个 issue&#xff1a;一个关于 yield across a C-call boundary 的问题&#xff0c;云风的解释是…

轮廓系数(Average silhouette) | 最佳聚类数的判定

1.最佳分类个数 # 辅助确定最佳聚类数 4.7*2.6 factoextra::fviz_nbclust( t(DPAU_2), kmeans, method "silhouette")在2有下降拐点&#xff0c;但是样本较多时分成2类一般意义不大。 在7时也有下降拐点。 2.查看每个分类的轮廓系数 (1) pam k5 library(cluste…

【Paddle】Inplace相关问题:反向传播、影响内存使用和性能

【Paddle】Inplace相关问题&#xff1a;反向传播、影响内存使用和性能 写在最前面inplace 的好处有哪些&#xff1f;能降低计算复杂度吗在反向传播时&#xff0c;Inplace为什么会阻碍呢&#xff1f;“计算图的完整性受损”表达有误原地操作 sin_()为什么原地操作会阻碍反向传播…