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

Gin框架基础

1、一个简单的Gin示例

下载并安装Gin:

go get -u github.com/gin-gonic/gin

1.1 一个简单的例子

package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {// 创建一个默认的路由引擎r := gin.Default()// 当客户端以GET方式访问 /hello 时,会执行后面的匿名函数,返回Hello Worldr.GET("/hello", func(ctx *gin.Context) {ctx.String(http.StatusOK, "Hello World")})r.GET("/json", func(ctx *gin.Context) {ctx.JSON(http.StatusOK, gin.H{"message": "Hello World",})})// 在8080端口监听r.Run(":8080")
}

使用浏览器打开127.0.0.1:8080/hello就能看到一串字符串,打开127.0.0.1:8080/json就能看到一串JSON字符串。
在这里插入图片描述

1.2 RESTful API

Gin 如何处理 GET, POST, PUT, PATCH, DELETE 和 OPTIONS 请求
Gin 处理各种 HTTP 请求是非常简单的,只要使用 router.XXX 方法即可注册处理器。其中 XXX 是 HTTP 请求方法的大写模式。

也就是说,Gin框架支持开发RESTful API的开发。
在这里插入图片描述

package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {// 创建一个默认的路由引擎r := gin.Default()//r.GET("/book", func(ctx *gin.Context) {ctx.JSON(http.StatusOK, gin.H{"message": "GET",})})r.POST("/book", func(ctx *gin.Context) {ctx.JSON(http.StatusOK, gin.H{"message": "POST",})})r.PUT("/book", func(ctx *gin.Context) {ctx.JSON(http.StatusOK, gin.H{"message": "PUT",})})r.DELETE("/book", func(ctx *gin.Context) {ctx.JSON(http.StatusOK, gin.H{"message": "DELETE",})})// 在8080端口监听r.Run(":8080")
}

开发RESTful API的时候我们通常使用Postman来作为客户端的测试工具。

在这里插入图片描述

2、获取参数

2.1、如何获取 GET 查询字符串参数?

查询字符串参数就是 URL 中 ? 后面 # 之前的参数,比如下面的 URL,
https://www.xxxxx.cn/user/search?username=金克斯&address=艾欧尼亚#reply0
查询字符串参数特指 username=金克斯&address=艾欧尼亚

Gin 的 Handler 提供了 以下几种方式

方法说明
ctx.Query()获取查询参数,如果参数不存在或值为空则返回空字符串 “”
ctx.DefaultQuery()获取查询参数,如果参数不存在或值为空则返回第二个参数做为值
ctx.GetQuery()类似于 c.Query(),但同时返回第二个 bool 参数用于判断该参数到底存不存在
  1. ctx.Query()
ctx.Query("username")	// 返回"金克斯"
ctx.Query("address")	// 返回"艾欧尼亚"
ctx.Query("gender")		// 返回""
  1. ctx.DefaultQuery()
ctx.DefaultQuery("username", "none")	// 返回"金克斯"
ctx.DefaultQuery("address", "none")		// 返回"艾欧尼亚"
ctx.DefaultQuery("gender", "none")		// 返回"none"
  1. ctx.GetQuery()
ctx.GetQuery("username")	// 返回("金克斯", true)
ctx.GetQuery("address") 	// 返回("艾欧尼亚", true)
ctx.GetQuery("gender")		// 返回("", false)

例子

package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {// 创建一个默认的路由引擎router := gin.Default()// 解析/user/search?username=金克斯&address=艾欧尼亚#reply0router.GET("/user/search", func(ctx *gin.Context) {username := ctx.Query("username")address, _ := ctx.GetQuery("address")gender := ctx.DefaultQuery("gender", "none")ctx.JSON(http.StatusOK, gin.H{"username": username,"address": address,"gender": gender,})})// 在8080端口监听router.Run(":8080")
}

浏览器返回http://127.0.0.1:8080/user/search?username=金克斯&address=艾欧尼亚#reply0,返回

{"address":"艾欧尼亚","gender":"none","username":"金克斯"}

2.2、如何获取 POST 表单form数据

Gin 提供了三个类似的方法用于获取 POST 请求提交的参数

方法说明
ctx.PostForm()获取 POST 表单参数,如果参数不存在或值为空则返回空字符串 “”
ctx.DefaultPostForm()获取 POST 表单参数,如果参数不存在或值为空则返回第二个参数做为值
ctx.GetPostForm()类似于 c.PostForm(),但同时返回第二个 bool 参数用于判断该参数到底存不存在
package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {// 创建一个默认的路由引擎router := gin.Default()// 解析/user/search?username=金克斯&address=艾欧尼亚#reply0router.POST("/user/search", func(ctx *gin.Context) {username := ctx.PostForm("username")address, _ := ctx.GetPostForm("address")gender := ctx.DefaultPostForm("gender", "none")ctx.JSON(http.StatusOK, gin.H{"username": username,"address": address,"gender": gender,})})// 在8080端口监听router.Run(":8080")
}

使用postman发送表单请求
在这里插入图片描述

2.3、如何同时获取 GET 数据和 POST 数据

package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {router := gin.Default()router.POST("user/search", func(ctx *gin.Context) {query_name := ctx.Query("name")query_address := ctx.Query("address")post_name := ctx.PostForm("name")post_address := ctx.PostForm("address")ctx.JSON(http.StatusOK, gin.H{"query_name": query_name,"query_address": query_address,"post_name": post_name,"post_address": post_address,})})router.Run(":8080")}

在这里插入图片描述

2.4、如何获取路由参数

在没有路由参数之前,如果我们想获取/user/1/user/2的用户数据,我们需要注册多个路由器

router.GET("/user/1", func(c *gin.Context) {})
router.GET("/user/2", func(c *gin.Context) {})

如果用户量大了,这个注册显然不靠谱。

Gin 允许我们使用 :[参数名] *[参数名] 来注册一个路由参数,比如上面的用户详情就可以注册为 /user/:user_id。然后我们就可以在路由 Handler 中通过 c.Param("user_id")获取到这个参数。

  • :[参数名] :路由参数能够匹配任何字符串,除了路径分隔符 /。 也就是说 /user/:user_id 可以匹配 /user/1 但不能匹配 /user/1/message
	router.GET("/user/:name", func(ctx *gin.Context) {name := ctx.Param("name")ctx.JSON(http.StatusOK, gin.H{"message": name,})})/*127.0.0.1:8080/user/金克斯, 返回 {"message":"金克斯"}127.0.0.1:8080/user/金克斯/艾欧尼亚, 返回 404 page not found*/
  • *[参数名] :路由参数可以匹配任意字符,包括/,也就是说 /user/:user_id 可以匹配 /user/1 也可以能匹配 /user/1/message ,还能匹配 /user/1/message/a/b/c/d/e
	router.GET("/user/:name/*address", func(ctx *gin.Context) {name := ctx.Param("name")address := ctx.Param("address")ctx.JSON(http.StatusOK, gin.H{"message": name,"address": address,})})/*127.0.0.1:8080/user/金克斯, 返回 {"address":"/","message":"金克斯"}127.0.0.1:8080/user/金克斯/艾欧尼亚, 返回 {"address":"/艾欧尼亚","message":"金克斯"}*/

Gin 的路由定义遵循几个规范

  • 和访问路径一样的路由定义(精确路由) 将会被优先匹配。 比如
	router.GET("/user/:name", func(ctx *gin.Context) {name := ctx.Param("name")ctx.JSON(http.StatusOK, gin.H{"message": name,})})// 精确路由(相对于有路由参数的路由)会被优先匹配,而无论他们在哪里定义router.GET("/user/groups", func(c *gin.Context) {c.String(http.StatusOK, "The available groups are [...]")})
  • 默认情况下,如果先定义的路由匹配了,那么后续定义的路由就不会被匹配。

2.5、如何接受表单中的字典(Map)参数

Gin 提供了 ctx.QueryMap() 用于获取字典形式的查询字符串参数,提供了ctx.PostFormMap()用于获取字典形式的 POST 表单参数。

package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {router := gin.Default()router.POST("/post", func(ctx *gin.Context) {ids := ctx.QueryMap("ids")names := ctx.PostFormMap("names")ctx.JSON(http.StatusOK, gin.H{"ids": ids,"names": names,})})router.Run(":8080")}

在这里插入图片描述

2.6、如何对请求参数模型绑定和验证

为了能够更方便的获取请求相关参数,提高开发效率,我们可以基于请求的Content-Type识别请求数据类型并利用反射机制自动提取请求中QueryStringform表单JSONXML等参数到结构体中。
原理都是一样的: 需要在要绑定的所有字段上,设置相应的 tag。例如,使用 JSON 绑定时,设置字段标签为 json:"fieldname"

Gin 框架提供了两类绑定方法:

  • 第一类: 必须绑定 (Must Bind),BindXXX() 方法,如果绑定出错则会直接抛出 400 错误:
    方法有: Bind(), BindJSON(), BindXML(), BindQuery(), BindYAML(), BindHeader(), BindTOML()。

  • 第二类: 应该绑定 (Should bind),ShouldBindXXX() 等方法,如果绑定出错则会抛出异常
    方法有: ShouldBind(), ShouldBindJSON(), ShouldBindXML(), ShouldBindQuery(), ShouldBindYAML(), ShouldBindHeader(), ShouldBindTOML(),

这些方法具体的实现调用了 ShouldBindWith()。 如果发生绑定错误,Gin 会返回错误并由开发者处理错误和请求。

package mainimport ("net/http""github.com/gin-gonic/gin"
)type Login struct {Username string `form:"username" json:"username" binding:"required"`Password string `form:"password" json:"password" binding:"required"`
}func main() {router := gin.Default()// 绑定JSON的示例 ({"username": "admin", "password": "123456"})router.POST("/loginJson", func(ctx *gin.Context) {var login Login// ShouldBind()会根据请求的Content-Type自行选择绑定器if err := ctx.ShouldBind(&login); err != nil {ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}if login.Username == "admin" && login.Password == "123456" {ctx.JSON(http.StatusOK, gin.H{"status":   "you are logged in","username": login.Username,"password": login.Password,})} else {ctx.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})}})// 绑定form表单示例router.POST("/loginForm", func(ctx *gin.Context) {var login Login// ShouldBind()会根据请求的Content-Type自行选择绑定器if err := ctx.ShouldBind(&login); err != nil {ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}if login.Username == "admin" && login.Password == "123456" {ctx.JSON(http.StatusOK, gin.H{"status":   "you are logged in","username": login.Username,"password": login.Password,})} else {ctx.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})}})// 绑定QueryString示例router.GET("loginQuery", func(ctx *gin.Context) {var login Login// ShouldBind()会根据请求的Content-Type自行选择绑定器if err := ctx.ShouldBind(&login); err != nil {ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}if login.Username == "admin" && login.Password == "123456" {ctx.JSON(http.StatusOK, gin.H{"status":   "you are logged in","username": login.Username,"password": login.Password,})} else {ctx.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})}})router.Run(":8080")}

绑定JSON
在这里插入图片描述
绑定form表单
在这里插入图片描述
绑定QueryString
在这里插入图片描述
需要注意的是,如果没有输入password,是会报错的。是因为tag中的binding:"required"进行了限制。如果将 Password 改为 binding:"-", 再次运行上面的示例就不会返回错误。

Password string `form:"password" json:"password" binding:"required"`

参考资料

李文周的博客
Gin 框架中文文档

相关文章:

Gin框架基础

1、一个简单的Gin示例 下载并安装Gin: go get -u github.com/gin-gonic/gin1.1 一个简单的例子 package mainimport ("net/http""github.com/gin-gonic/gin" )func main() {// 创建一个默认的路由引擎r : gin.Default()// 当客户端以GET方式访问 /hello…...

用GPT-4纠错GPT-4 OpenAI推出CriticGPT模型

根据OpenAI周四(6月27日)发布的新闻稿,该公司新推出了一个基于GPT-4的模型——CriticGPT,用于捕获ChatGPT代码输出中的错误。CriticGPT的作用相当于让人们用GPT-4来查找GPT-4的错误。该模型可以对ChatGPT响应结果做出批评评论&…...

SQL CASE WHEN语句的使用技巧

SQL CASE WHEN语句的使用技巧 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 在SQL查询中,经常需要根据不同的条件进行分支处理,这时就…...

虹科技术丨跨越距离障碍:PCAN系列网关在远程CAN网络通信的应用潜力

来源:虹科技术丨跨越距离障碍:PCAN系列网关在远程CAN网络通信的应用潜力 原文链接:虹科技术 | 跨越距离障碍:PCAN系列网关在远程CAN网络通信的应用潜力 欢迎关注虹科,为您提供最新资讯! #PCAN #网关 #CA…...

【UE 网络】RPC远程过程调用 入门篇

目录 0 引言1 RPC基本概念1.1 定义1.2 分类 2 RPC的使用2.1 Client RPC2.2 Server RPC2.3 Multicast RPC 🙋‍♂️ 作者:海码007📜 专栏:UE虚幻引擎专栏💥 标题:【UE 网络】RPC远程过程调用 入门篇❣️ 寄语…...

安装maven与nexus

安装maven与nexus Maven官网下载地址:http://maven.apache.org cd /data/software/wget https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.8.1/binaries/apache-maven-3.8.8-bin.tar.gz# 解压 tar xf apache-maven-3.8.1-bin.tar.gz -C /opt/[rooth…...

如何用DCA1000持续采集雷达数据

摘要:本文介绍一下如何通过mmwave studio软件,搭配DCA1000数据采集卡,对AWR1843BOOST进行不间断的数据采集。本文要求读者已经掌握了有关基础知识。 本文开放获取,无需关注。 到SensorConfig页面下,一步步操作&#xf…...

怎么用JavaScript写爬虫

随着互联网技术的不断发展,爬虫(web crawler)已经成为当前最热门的爬取信息方式之一。通过爬虫技术,我们可以轻松地获取互联网上的数据,并用于数据分析、挖掘、建模等多个领域。而javascript语言则因其强大的前端开发工…...

Leetcode 3203. Find Minimum Diameter After Merging Two Trees

Leetcode 3203. Find Minimum Diameter After Merging Two Trees 1. 解题思路2. 代码实现 题目链接:3203. Find Minimum Diameter After Merging Two Trees 1. 解题思路 这一题的话算是一个拓扑树的题目?总之就是从树的叶子节点不断向上遍历&#xff…...

【抽代复习笔记】24-群(十八):循环群的两道例题

例1:证明: (1)三次交错群A3是循环群,它与(Z3,)同构,其中Z3 {[0],[1],[2]}; (2)G {1,i,-1,-i},G上的代数运算是数的乘法,则G是一个循环群&…...

Linux常见操作问题

1、登录刚创建的用户,无法操作。 注:etc/passwd文件是Linux操作系统中存储用户账户信息的文本文件,包含了系统中所有用户的基本信息,比如用户名、用户ID、用户组ID、用户家目录路径。 注:etc: 这个目录存放所有的系统…...

鲁工小装载机-前后桥传动轴油封更换记录

鲁工装载机 因前后桥大量漏齿轮油,故拆开查看、更换油封 一: 如图圈起来的地方是螺丝和钢板相别,用200的焊接电流用电焊机点开一个豁口后拆除螺丝。 转轴是拆除传动轴后的样子。 这就是拆下来的样子,这玩意插上边那图&…...

商城自动化测试实战 —— 登录+滑块验证

hello大家好,我是你们的小编! 本商城测试项目采取PO模型和数据分离式架构,采用pytestseleniumjenkins结合的方式进行脚本编写与运行,项目架构如下: 1、创建项目名称:code_shopping,创建所需项目…...

8.计算机视觉—增广和迁移

目录 1.数据增广数据增强数据增强的操作代码实现2.微调 迁移学习 Transfer learning(重要的技术)网络结构微调:当目标数据集比源数据集小得多时,微调有助于提高模型的泛化能力。训练固定一些层总结代码实现1.数据增广 CES上的真实故事 有一家做智能售货机的公司,发现他们…...

【Matlab】-- BP反向传播算法

文章目录 文章目录 00 写在前面01 BP算法介绍02 基于Matlab的BP算法03 代码解释 00 写在前面 BP算法可以结合鲸鱼算法、飞蛾扑火算法、粒子群算法、灰狼算法、蝙蝠算法等等各种优化算法一起,进行回归预测或者分类预测。 01 BP算法介绍 BP(Backpropag…...

【Python】 数据分析中的常见统计量:众数

那年夏天我和你躲在 这一大片宁静的海 直到后来我们都还在 对这个世界充满期待 今年冬天你已经不在 我的心空出了一块 很高兴遇见你 让我终究明白 回忆比真实精彩 🎵 王心凌《那年夏天宁静的海》 众数(Mode)是统计学中另…...

Karabiner-Elements 设置mac键盘

软件下载地址: Karabiner-Elements 修改键盘位置,但是重启后,就消失了。 {"description": "New Rule (change left_shiftcaps_lock to page_down, right_shiftcaps_lock to left_commandmission_control)","manip…...

Mybatis实现流程

一&#xff0c;UserDAO 接口定义 首先&#xff0c;定义 UserDAO接口&#xff0c;包含 getList()方法,定义类型为List<User>&#xff1a; package dao;import model.User; import java.util.List;public interface UserDAO {List<User> getList(); }二&#xff0c…...

简单的springboot整合activiti5-serviceImpl部分(1)

简单的springboot整合activiti5.22.0-serviceImpl部分(1) 原来的流程serviceImpl部分代码过多&#xff0c;所以此处单独记录一下&#xff0c;此处记录的是serviceImpl第一部分代码 package cn.git.workflow.service.impl;import cn.git.cache.api.BaseCacheApi; import cn.gi…...

snat、dnat和firewalld

目录 概述 SNAT源地址转换 DANT目的地址转换 抓包 firewalld 端口管理 概述 snat &#xff1a;源地址转换 内网——外网 内网ip转换成可以访问外网的ip 也就是内网的多个主机可以只有一个有效的公网ip地址访问外部网络 DNAT&#xff1a;目的地址转发 外部用户&#…...

书匠策AI毕业论文功能全拆解:一个教论文写作的博主,居然被它种草了

你还在对着空白文档发呆&#xff1f;这个AI工具让我"真香"了 各位同学&#xff0c;我是你们的论文写作科普博主。 说句大实话&#xff0c;这几年我教过上千个学生怎么写毕业论文&#xff0c;从选题到开题、从大纲到终稿&#xff0c;每个环节我都能给你掰碎了讲。但…...

多视角卷积神经网络(MVCNN)如何用二维图像实现三维物体识别?

多视角卷积神经网络&#xff08;MVCNN&#xff09;如何用二维图像实现三维物体识别&#xff1f; 【免费下载链接】mvcnn_pytorch MVCNN on PyTorch 项目地址: https://gitcode.com/gh_mirrors/mv/mvcnn_pytorch 在计算机视觉领域&#xff0c;三维物体识别一直是一个具有…...

完全掌握Adobe软件激活:5个实用技巧深度解析

完全掌握Adobe软件激活&#xff1a;5个实用技巧深度解析 【免费下载链接】Adobe-GenP Adobe CC 2019/2020/2021/2022/2023 GenP Universal Patch 3.0 项目地址: https://gitcode.com/gh_mirrors/ad/Adobe-GenP 你是否曾经为Adobe Creative Cloud的订阅费用感到困扰&…...

企业级AI助手私有化部署:Open WebUI完全指南

企业级AI助手私有化部署&#xff1a;Open WebUI完全指南 【免费下载链接】open-webui User-friendly AI Interface (Supports Ollama, OpenAI API, ...) 项目地址: https://gitcode.com/GitHub_Trending/op/open-webui 在数据安全和隐私保护日益重要的今天&#xff0c;企…...

syncpack 迁移指南:从 v13 到 v14 的完整步骤与注意事项

syncpack 迁移指南&#xff1a;从 v13 到 v14 的完整步骤与注意事项 【免费下载链接】syncpack Consistent dependency versions in large JavaScript Monorepos. 项目地址: https://gitcode.com/gh_mirrors/sy/syncpack syncpack 是一款专为大型 JavaScript Monorepo 设…...

别再只用EC11调音量了!用STM32做个旋转编码器计数器(OLED显示,附防抖代码)

解锁EC11旋转编码器的计数潜能&#xff1a;STM32实战指南与防抖优化 旋转编码器在电子项目中常被简化为音量调节工具&#xff0c;但其真正的价值远不止于此。EC11作为一款经济高效的旋转编码器&#xff0c;能够提供精确的数字脉冲信号&#xff0c;非常适合需要精准位置控制或速…...

基于Telegram的AI智能体框架:从原理到实践部署指南

1. 项目概述&#xff1a;一个基于Telegram的AI智能体框架最近在GitHub上看到一个挺有意思的项目&#xff0c;叫openclaw-telegram-ai-agent。光看名字&#xff0c;你大概能猜到它是个什么东西&#xff1a;一个运行在Telegram平台上的AI智能体&#xff08;Agent&#xff09;。但…...

8款投屏软件亲测对比:哪款才是真正的“良心之选”?

市面上的投屏软件多如牛毛&#xff0c;但真正好用的没几个。为了帮大家避坑&#xff0c;我亲自下载、安装、使用了8款常见的投屏工具&#xff0c;从是否收费、有无广告、功能丰富度、兼容性、实际体验五个维度做了深度测试。下面是我的真实使用感受&#xff0c;希望对你有帮助。…...

使用Python快速接入Taotoken聚合大模型API的简明教程

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 使用Python快速接入Taotoken聚合大模型API的简明教程 本文面向希望快速集成大模型能力的Python开发者&#xff0c;介绍如何通过官方…...

基于RAG与FastAPI构建AI知识库插件:从原理到实战

1. 项目概述与核心价值最近在折腾AI智能体&#xff0c;特别是给ChatGPT这类大语言模型加装“插件”或“工具”时&#xff0c;发现了一个挺有意思的项目&#xff1a;urantia-hub/urantia-papers-plugin。乍一看这个名字&#xff0c;可能很多开发者会有点懵&#xff0c;这到底是做…...