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

【GO基础学习】gin的使用

文章目录

  • 模版使用流程
  • 参数传递
  • 路由分组
  • 数据解析和绑定
  • gin中间件


模版使用流程

package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {// 1.创建路由r := gin.Default()// 2.绑定路由规则,执行的函数// gin.Context,封装了request和responser.GET("/", func(c *gin.Context) {c.String(http.StatusOK, "hello World!")})// 3.监听端口,默认在8080// Run("里面不指定端口号默认为8080") r.Run(":8000")
}

运行,访问:http://localhost:8000/

在这里插入图片描述
后面为了减少累赘代码,只展示路由规则部分代码编写,创建路由,以及端口监听部分代码保存相同。


参数传递

  1. API传参:可以通过Context的Param方法来获取API参数。
r.GET("/user/:name", func(c *gin.Context) {name := c.Param("name")c.String(http.StatusOK, "Hello "+name+"!")})

在这里插入图片描述

r.GET("/user/:name/*action", func(c *gin.Context) {name := c.Param("name")action := c.Param("action")c.String(http.StatusOK, "Hello "+name+"!"+"Action "+action)})

在这里插入图片描述

*action 表示一个通配路径参数,可以匹配 URL 剩余部分的路径,并且会包含匹配部分的斜杠 /

  1. URL传参:URL参数可以通过DefaultQuery()Query()方法获取,DefaultQuery()若参数不存在,返回默认值,Query()若不存在,返回空串。

DefaultQuery默认值只支持string类型:

func (c *Context) DefaultQuery(key, defaultValue string) string {if value, ok := c.GetQuery(key); ok {return value}return defaultValue
}
r.GET("/user", func(c *gin.Context) {name := c.DefaultQuery("name", "Test")ageStr := c.DefaultQuery("age", "18")age, err := strconv.Atoi(ageStr)if err != nil {c.String(http.StatusBadRequest, "Invalid age")return}c.String(http.StatusOK, fmt.Sprintf("%s is %d years old", name, age))})

在这里插入图片描述

  1. 表单传值
<form action="http://localhost:8000/form" method="post" action="application/x-www-form-urlencoded">用户名:<input type="text" name="username" placeholder="请输入你的用户名">  <br>&nbsp;&nbsp;&nbsp;码:<input type="password" name="userpassword" placeholder="请输入你的密码">  <br><input type="submit" value="提交"></form>
r.POST("/form", func(c *gin.Context) {types := c.DefaultPostForm("type", "post")username := c.PostForm("username")password := c.PostForm("userpassword")c.String(http.StatusOK, fmt.Sprintf("username:%s,password:%s,type:%s", username, password, types))})
  1. 文件上传

单个文件:

<form action="http://localhost:8000/upload" method="post" enctype="multipart/form-data">上传文件:<input type="file" name="file" ><input type="submit" value="提交"></form>
// 限制上传文件大小 (10 MiB)r.MaxMultipartMemory = 10 << 20 // 10 MiB// 文件上传路由r.POST("/upload", func(c *gin.Context) {// 获取文件file, err := c.FormFile("file")if err != nil {c.String(http.StatusBadRequest, "File upload error: %s", err.Error())return}// 检查文件类型 (仅允许 image/png)mimeType := file.Header.Get("Content-Type")if mimeType != "image/png" {c.String(http.StatusBadRequest, "Invalid file type: %s. Only PNG images are allowed.", mimeType)return}// 保存文件到目标路径dst := filepath.Join("./uploads", file.Filename)if err := c.SaveUploadedFile(file, dst); err != nil {c.String(http.StatusInternalServerError, "Could not save file: %s", err.Error())return}c.String(http.StatusOK, "File uploaded successfully: %s", file.Filename)})

多个文件:

// 限制上传文件大小 (10 MiB)r.MaxMultipartMemory = 10 << 20 // 10 MiB// 多文件上传路由r.POST("/upload/multiple", func(c *gin.Context) {// 获取表单文件 (key 为 "files")form, err := c.MultipartForm()if err != nil {c.String(http.StatusBadRequest, "Form error: %s", err.Error())return}files := form.File["files"] // 获取多个文件for _, file := range files {// 检查文件类型 (仅允许 image/png)mimeType := file.Header.Get("Content-Type")if mimeType != "image/png" {c.String(http.StatusBadRequest, "Invalid file type: %s for file: %s. Only PNG images are allowed.", mimeType, file.Filename)return}// 保存文件到目标路径dst := filepath.Join("./uploads", file.Filename)if err := c.SaveUploadedFile(file, dst); err != nil {c.String(http.StatusInternalServerError, "Could not save file: %s. Error: %s", file.Filename, err.Error())return}fmt.Printf("Uploaded file: %s\n", file.Filename)}c.String(http.StatusOK, "All files uploaded successfully")})

路由分组

在 Gin 框架中,路由分组(Route Group)是用于组织和管理路由的功能。通过路由分组,可以为一组路由添加公共的前缀、中间件或配置,从而提高代码的可读性和可维护性。

package mainimport ("github.com/gin-gonic/gin""net/http"
)func main() {// 1.创建路由r := gin.Default()// 2.绑定路由规则,执行的函数// gin.Context,封装了request和response// 用户路由组userGroup := r.Group("/user"){userGroup.GET("/login", login)userGroup.GET("/settings", func(c *gin.Context) {c.JSON(200, gin.H{"message": "User Settings"})})}// 管理员路由组adminGroup := r.Group("/admin"){adminGroup.GET("/dashboard", func(c *gin.Context) {c.JSON(200, gin.H{"message": "Admin Dashboard"})})adminGroup.GET("/reports", func(c *gin.Context) {c.JSON(200, gin.H{"message": "Admin Reports"})})}// 404r.NoRoute(func(c *gin.Context) {c.String(http.StatusNotFound, "404 not found !!!!")})// 3.监听端口,默认在8080// Run("里面不指定端口号默认为8080")r.Run(":8000")
}func login(c *gin.Context) {name := c.DefaultQuery("name", "jack")c.JSON(200, gin.H{"name": name})
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


数据解析和绑定

  1. JSON数据解析和绑定的基本步骤

(1) 定义结构体

定义一个与 JSON 数据格式匹配的 Go 结构体。

(2) 使用 c.BindJSONc.ShouldBindJSON

  • c.BindJSON 会在绑定失败时返回错误并终止请求。
  • c.ShouldBindJSON 返回错误但不会中断后续处理,适合灵活的错误处理场景。

(3) 使用结构体处理数据

通过绑定的结构体直接访问解析后的字段。

package mainimport ("net/http""github.com/gin-gonic/gin"
)type User struct {Name  string `json:"name" binding:"required"` // 必填字段Age   int    `json:"age" binding:"required"`  // 必填字段Email string `json:"email"`                  // 可选字段
}func main() {r := gin.Default()r.POST("/user", func(c *gin.Context) {var user Userif err := c.ShouldBindJSON(&user); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}c.JSON(http.StatusOK, gin.H{"message": "User data received","user":    user,})})r.Run(":8080")
}

在这里插入图片描述

Gin 提供了 binding 标签,用于对字段进行验证。支持多种验证规则。

type User struct {Name  string `json:"name" binding:"required,min=3"` // 必填,最小长度 3Age   int    `json:"age" binding:"required,gte=1"`  // 必填,必须大于等于 1Email string `json:"email" binding:"required,email"` // 必填,必须是合法邮箱
}
验证规则含义
required必须提供该字段
min字符串或切片的最小长度
max字符串或切片的最大长度
gte数字或时间的值必须大于等于指定值
lte数字或时间的值必须小于等于指定值
email必须是有效的邮箱地址

  1. 表单数据:
    为字段添加多种绑定方式的标签,例如 jsonform 标签。

Gin 会根据 Content-Type 自动选择适合的绑定方式:

  • 如果是 application/json,则绑定 JSON 数据。
  • 如果是 application/x-www-form-urlencodedmultipart/form-data,则绑定表单数据。
type User struct {Name  string `json:"name" form:"name" binding:"required"` // 必填字段Age   int    `json:"age" form:"age" binding:"required,gte=0"`Email string `json:"email" form:"email"`
}
  1. URI数据

通过 c.Param 获取路径参数的值

package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {r := gin.Default()r.GET("/user/:id", func(c *gin.Context) {id := c.Param("id") // 提取路径参数c.JSON(http.StatusOK, gin.H{"user_id": id,})})r.Run(":8080")
}

Gin 提供了 ShouldBindUri 方法,可以将路径参数直接绑定到结构体中,方便处理和验证。

package mainimport ("net/http""github.com/gin-gonic/gin"
)type UserRequest struct {ID string `uri:"id" binding:"required"` // 使用 `uri` 标签定义路径参数
}func main() {r := gin.Default()r.GET("/user/:id", func(c *gin.Context) {var req UserRequest// 将路径参数绑定到结构体if err := c.ShouldBindUri(&req); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}c.JSON(http.StatusOK, gin.H{"user_id": req.ID,})})r.Run(":8080")
}
  1. 路径参数可以和查询参数或表单参数结合使用。Gin 支持同时解析这些参数。
package mainimport ("net/http""github.com/gin-gonic/gin"
)type UserRequest struct {ID   string `uri:"id" binding:"required"`  // 路径参数Name string `form:"name"`                 // 查询参数或表单参数
}func main() {r := gin.Default()r.GET("/user/:id", func(c *gin.Context) {var req UserRequest// 绑定路径参数if err := c.ShouldBindUri(&req); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}// 绑定查询参数if err := c.ShouldBindQuery(&req); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}c.JSON(http.StatusOK, gin.H{"user_id": req.ID,"name":    req.Name,})})r.Run(":8080")
}
GET /user/123?name=Alice

gin中间件

在 Gin 中,中间件是一个可以插入到请求处理流程中的函数,用于实现请求前后的通用逻辑。例如,认证、日志记录、跨域处理等都可以通过中间件实现。

  1. 中间件定义
func(c *gin.Context) {// 执行逻辑c.Next() // 调用后续处理函数// 执行逻辑
}

c.Next():调用下一个中间件或处理程序。
c.Abort():停止执行后续的中间件和处理程序。

  1. 全局中间件

全局中间件会应用到所有路由,使用 r.Use() 注册。

package mainimport ("fmt""github.com/gin-gonic/gin"
)func Logger() gin.HandlerFunc {return func(c *gin.Context) {// 请求前逻辑fmt.Println("Request URL:", c.Request.URL.Path)c.Next() // 执行后续处理// 请求后逻辑fmt.Println("Response Status:", c.Writer.Status())}
}func main() {r := gin.Default()// 注册全局中间件r.Use(Logger())r.GET("/ping", func(c *gin.Context) {fmt.Println("=======11111111")c.String(200, "pong")})r.Run(":8080")
}

控制台输出:

Request URL: /ping
=======11111111
Response Status: 200

流程:中间件逻辑=》遇到next方法后,执行路由func=》中间件后面的逻辑。

  1. 局部中间件

局部中间件只应用于特定路由或路由组。

package mainimport ("github.com/gin-gonic/gin"
)func AuthRequired() gin.HandlerFunc {return func(c *gin.Context) {token := c.GetHeader("Authorization")if token != "valid-token" {c.AbortWithStatusJSON(401, gin.H{"error": "unauthorized"})return}c.Next()}
}func main() {r := gin.Default()// 局部中间件r.GET("/secure", AuthRequired(), func(c *gin.Context) {c.JSON(200, gin.H{"message": "Authorized"})})r.Run(":8080")
}

相关文章:

【GO基础学习】gin的使用

文章目录 模版使用流程参数传递路由分组数据解析和绑定gin中间件 模版使用流程 package mainimport ("net/http""github.com/gin-gonic/gin" )func main() {// 1.创建路由r : gin.Default()// 2.绑定路由规则&#xff0c;执行的函数// gin.Context&#x…...

网卡状态变更,virtio-net检测

实现方案&#xff1a; 现在在amp模式下linux端有个真实的物理网卡eth0&#xff0c;有一个虚拟网卡virtio-net0后端&#xff0c;此时需要一种机制&#xff0c;将真实物理网卡的状态发送rtos的virtio-net0前端。这里使用register_netdevice_notifier机制&#xff0c;每个virtio-n…...

中华人民共和国保守国家秘密法

中华人民共和国保守国家秘密法 &#xff08;1988年9月5日第七届全国人民代表大会常务委员会第三次会议通过 2010年4月29日第十一届全国人民代表大会常务委员会第十四次会议第一次修订 2024年2月27日第十四届全国人民代表大会常务委员会第八次会议第二次修订&#xff09; 目…...

ELK日志收集系统部署

1、 ElasticSearch部署 Elastic — 搜索 AI 公司 | Elastic 系统类型&#xff1a;Centos7.4 节点IP&#xff1a;172.16.246.234 软件版本&#xff1a;jdk-8u191-linux-x64.tar.gz、elasticsearch-6.5.4.tar.gz 示例节点&#xff1a;172.16.246.234 1、安装配置jdk8 ES运行依…...

3D线上艺术展:艺术与技术的完美融合

随着数字技术的飞速发展&#xff0c;未来的艺术展览正逐步迈向线上线下融合的新阶段。其中&#xff0c;3D线上展览以其独特的魅力&#xff0c;成为线下展览的延伸与拓展&#xff0c;为艺术爱好者们开辟了全新的观赏途径。 对于艺术家和策展人而言&#xff0c;3D线上展览不仅打…...

TiDB 的MPP架构概述

MPP架构介绍&#xff1a; 如图&#xff0c;TiDB Server 作为协调者&#xff0c;首先 TiDB Server 会把每个TiFlash 拥有的region 会在TiFlash上做交换&#xff0c;让表连接在一个TiFlash上。另外 TiFlash会作为计算节点&#xff0c;每个TiFlash都负责数据交换&#xff0c;表连接…...

Leetcode 10-正则表达式匹配/ 剑指 Offer 19. 正则表达式匹配

给你一个字符串 s 和一个字符规律 p&#xff0c;请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。 ‘.’ 匹配任意单个字符 ‘*’ 匹配零个或多个前面的那一个元素 所谓匹配&#xff0c;是要涵盖 整个 字符串 s 的&#xff0c;而不是部分字符串。 题解 字符串匹配多…...

FFmpeg 编码和解码

文章目录 音频格式AACADIF音频数据交换格式ADTS音频数据传输流 音频解码音频编码 视频格式H264GOP图像组I帧&#xff0c;P帧&#xff0c;B帧H264压缩技术H264压缩级别H264视频级别H264码流结构SPSPPS 解码视频编码视频 音频格式 AAC AAC全称 Advanced Audio Coding&#xff0…...

kali当中web扫描工具的用法

1. cadaver 用途&#xff1a;用于与WebDAV服务器交互&#xff0c;可进行文件上传、下载、目录浏览等操作。使用方法 连接到WebDAV服务器&#xff1a;cadaver <WebDAV服务器地址>&#xff0c;例如cadaver https://example.com/dav&#xff0c;然后按提示输入用户名和密码…...

深度剖析 Android Animation 框架

深度剖析 Android Animation 框架 目录 引言Android Animation 框架概述架构设计 3.1 核心类与接口3.2 动画类型3.3 动画执行流程使用指南 4.1 属性动画4.2 视图动画4.3 过渡动画设计模式 5.1 策略模式5.2 观察者模式5.3 工厂模式核心逻辑 6.1 动画插值器6.2 动画估值器6.3 动…...

泰山派GPIO子系统驱动---亮灯

本人linux驱动小白&#xff0c;文章基于B站up主 李Sir______ 视频内容记录&#xff0c;做笔记用。如有错误欢迎指正。本文将以开发板第40引脚GPIO3_B4作为LED灯珠的控制引脚&#xff0c;高电平灯亮&#xff0c;低电平灯灭。 杂话 在linux内核中&#xff0c;芯片厂商已经把所有…...

【C#特性整理】C#特性及语法基础

1. C#特性 1.1 统一的类型系统 C#中, 所有类型都共享一个公共的基类型. 例如&#xff0c;任何类型的实例都可以通过调用ToString方法将自身转换为一个字符串 1.2 类和接口 接口: 用于将标准与实现隔离, 仅仅定义行为,不做实现. 1.3 属性、方法、事件 属性: 封装了一部分对…...

Presence:Colyseus用于管理实时分布式数据的工具

Colyseus Presence 详细介绍 Presence 是 Colyseus 中用于管理实时分布式数据的一种工具。它主要用于在多房间、多服务器或分布式部署中实现玩家的实时在线状态、数据共享和通信。Presence 提供了一套简单的 API 来处理诸如在线玩家跟踪、分布式数据存储和发布/订阅模式等功能…...

Ubuntu 搭建SVN服务

目录 ​ 1、安装SVN服务端 2、创建SVN版本库 3、修改SVN配置svnserve.conf 3.1 配置文件介绍 3.2 svnserve.conf配置 3.3 authz配置设置用户读写权限 3.4 passwd配置 用户名密码 4、启动SVN服务 4.1 配置开机启动 1、安装SVN服务端 sudo apt-get install subversion…...

HTML速查

HTML 基本文档 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>文档标题</title></head><body>可见文本...</body> </html>基本标签&#xff08;Basic Tags&#xff09; <h1>最大的…...

day-102 二进制矩阵中的最短路径

思路 BFS 解题过程 从起点依次向八个方向尝试&#xff08;之后也一样&#xff09;&#xff0c;如果某个位置在矩阵内且值为0且没有访问过&#xff0c;将其添加到一个队列中&#xff0c;依次类推&#xff0c;直到到达出口 Code class Solution {public int shortestPathBinar…...

SQL Server大批量数据插入

数据库连接及相关操作 public class DataBase {/*** 驱动*/private static final String DRIVER PropertiesUtil.getString("spring.datasource.driver-class-name");/*** 数据库地址*/private static final String URL PropertiesUtil.getString("spring.da…...

在 Ubuntu 下通过 Docker 部署 Caddy 服务器

嘿&#xff0c;伙伴们&#xff01;今天我们来聊聊如何在 Ubuntu 系统下通过 Docker 部署 Caddy 服务器。Caddy 是一个现代的 Web 服务器&#xff0c;支持自动 HTTPS&#xff0c;简单易用&#xff0c;特别适合快速搭建网站。而 Docker 则是一个让你可以隔离和管理应用的神器。结…...

ZooKeeper注册中心实现

具体步骤 安装ZooKeeper&#xff08;启动端口占用&#xff0c;2181&#xff1a;客户端&#xff0c;8080&#xff1a;管理端&#xff09;引入客户端依赖实现注册中心接口SPI补充ZooKeeper注册中心 引入依赖 <!-- zookeeper --> <dependency><groupId>org.a…...

数仓建模:如何进行实体建模?

目录 1 如何进行实体建模? 业务建模 领域建模 逻辑建模 2 实体建模具体步骤 需求分析...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

FFmpeg:Windows系统小白安装及其使用

一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】&#xff0c;注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录&#xff08;即exe所在文件夹&#xff09;加入系统变量…...

Unity UGUI Button事件流程

场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...

恶补电源:1.电桥

一、元器件的选择 搜索并选择电桥&#xff0c;再multisim中选择FWB&#xff0c;就有各种型号的电桥: 电桥是用来干嘛的呢&#xff1f; 它是一个由四个二极管搭成的“桥梁”形状的电路&#xff0c;用来把交流电&#xff08;AC&#xff09;变成直流电&#xff08;DC&#xff09;。…...