20 go语言(golang) - gin框架安装及使用(一)
一、简介
Gin是一个用Go语言编写的高性能Web框架,专注于构建快速、可靠的HTTP服务。它以其速度和简洁性而闻名,非常适合用于开发RESTful API。
-
高性能:Gin使用了httprouter进行路由管理,这是一个轻量级且非常快速的HTTP请求路由器。
-
中间件支持:Gin提供了一种简单的方法来创建和使用中间件,可以在请求处理过程中执行额外的操作,如日志记录、身份验证等。
-
错误管理:内置了错误处理机制,可以在请求生命周期内捕获并处理错误,确保应用程序稳定运行。
-
JSON渲染:提供了便捷的方法来生成JSON响应,这对于构建API非常有用。
-
路由组:支持将路由组织成组,以便更好地管理复杂应用程序中的不同模块或版本控制。
-
优雅的API设计:提供了一套简洁易用的API,使得开发者可以快速上手并实现复杂功能。
二、安装
使用 go get 命令来下载并安装Gin包,详细参考官网文档:官方指引
go get -u github.com/gin-gonic/gin
三、使用
3.1 代码
下面是一个简单的示例程序,展示如何使用Gin创建一个Web服务器:
package mainimport ("github.com/gin-gonic/gin""net/http""testing"
)func Test1(t *testing.T) {// 创建一个带有Logger和Recovery中间件(用于日志记录和恢复崩溃)的默认Gin引擎。r := gin.Default()// 定义一个GET请求路由,当访问"/ping"时会调用指定匿名函数返回JSON响应。r.GET("/ping", func(c *gin.Context) {// 返回JSON格式的数据响应,其中`http.StatusOK`表示200状态码,而`gin.H{}`用于构造JSON对象。c.JSON(http.StatusOK, gin.H{"message": "pong",})})// 启动HTTP服务器,监听8080端口(如未指定端口,将默认为:8080)。r.Run(":8080")
}
3.2 运行程序
-
在goland中右键运行
-
打开浏览器或使用工具(如curl或Postman)访问
http://localhost:8080/ping后,JSON响应:{"message":"pong"}
四、组成
Gin 是一个用 Go 语言编写的高性能 HTTP Web 框架,特别适合用于构建微服务和快速开发 RESTful API。Gin 的组成主要包括以下几个核心部分:
-
Router(路由器)
- Gin 使用基于树结构的路由机制来处理 HTTP 请求。它支持动态路由参数、分组路由以及中间件。
- 路由器负责将请求路径映射到相应的处理函数。
-
Context(上下文)
gin.Context是 Gin 中最重要的结构之一,它在请求生命周期内传递信息。- Context 提供了对请求和响应对象的访问,以及用于存储数据、设置状态码、返回 JSON 等方法。
-
Middleware(中间件)
- 中间件是可以在请求被最终处理之前或之后执行的一段代码,用于实现日志记录、错误恢复、认证等功能。
- Gin 支持全局中间件和特定路由组或单个路由使用的中间件。
-
Handlers(处理函数)
- 处理函数是实际执行业务逻辑的位置,每个路由都会关联一个或多个处理函数。
- 这些函数接收
gin.Context参数,通过它们可以获取请求数据并生成响应。
-
Error Handling(错误处理)
- Gin 提供了一种机制来捕获和管理应用程序中的错误,可以通过 Context 的方法进行错误报告和恢复操作。
-
Rendering and Responses(渲染与响应)
- 支持多种格式的数据输出,包括 JSON、XML 和 HTML 渲染等,方便客户端消费不同类型的数据格式。
-
Binding and Validation(绑定与验证)
- 自动将 HTTP 请求中的数据绑定到结构体,并支持对输入数据进行验证,以确保其符合预期格式和规则。
-
Templates (模板)
- 虽然不是框架核心,但 Gin 支持集成 HTML 模板引擎,用于生成动态网页内容。
4.1 Router(路由器)
Gin 的路由器是其核心组件之一,负责将 HTTP 请求路径映射到相应的处理函数。它采用高效的树结构来管理路由,从而提高请求匹配速度。
4.1.1 基本路由
Gin 提供了简单的方法来定义基本的 HTTP 路由。例如,可以使用 GET, POST, PUT, DELETE 等方法来注册不同类型的请求。
func postTest(context *gin.Context) {context.JSON(http.StatusOK, gin.H{"message": "post_test_success",})
}func Test2(t *testing.T) {r := gin.Default()r.POST("/post_test", postTest)r.Run()
}

4.1.2 动态路由参数
支持在 URL 中定义动态参数,允许从 URL 中提取变量。
func Test3(t *testing.T) {r := gin.Default()r.GET("/get_test/:name", func(c *gin.Context) {name := c.Param("name")c.JSON(http.StatusOK, gin.H{"message": "hello:" + name,})})r.Run()}

4.1.3 查询字符串和表单参数
可以通过上下文对象轻松获取查询字符串和表单数据。
func Test4(t *testing.T) {r := gin.Default()r.POST("/form_post", func(c *gin.Context) {name := c.PostForm("name")nickname := c.DefaultPostForm("nickname", "昵称")c.JSON(200, gin.H{"name": name,"nickname": nickname,})})r.Run()
}

4.1.4 分组路由(Route Groups)
允许对一组具有共同前缀或中间件的路由进行分组管理。这有助于组织代码并应用共享行为。
func Test5(t *testing.T) {r := gin.Default()group := r.Group("/v1")handler := func(c *gin.Context) {println("调用了地址:" + c.Request.Host + c.Request.URL.Path)}{group.GET("/login", handler)group.GET("/submit", handler)group.GET("/listData", handler)}r.Run()
}
输出
调用了地址:localhost:8080/v1/login
[GIN] 2024/12/05 - 18:59:09 | 200 | 26.787µs | ::1 | GET "/v1/login"
调用了地址:localhost:8080/v1/submit
[GIN] 2024/12/05 - 18:59:24 | 200 | 11.511µs | ::1 | GET "/v1/submit"
调用了地址:localhost:8080/v1/listData
[GIN] 2024/12/05 - 18:59:31 | 200 | 10.746µs | ::1 | GET "/v1/listData"
4.1.5 优先级与冲突解决
Gin 的树形结构使得精确匹配路径比通配符路径优先级更高,因此 /v1/login 会比 /v1/:name 优先匹配。
func Test6(t *testing.T) {r := gin.Default()group := r.Group("/v1")handler := func(c *gin.Context) {println("调用了地址:" + c.Request.Host + c.Request.URL.Path)}handler2 := func(c *gin.Context) {name := c.Param("name")println("调用了地址:" + c.Request.Host + c.Request.URL.Path)c.JSON(http.StatusOK, gin.H{"message": "hello:" + name,})}{group.GET("/login", handler)group.GET("/:name", handler2)}r.Run()
}
4.2 Context(上下文)
gin.Context 是一个非常重要的结构体,它在每个请求的生命周期内被创建,并贯穿整个处理过程。上下文提供了丰富的方法和属性,用于简化请求数据的获取、响应生成以及中间件之间的数据共享。
4.2.1 请求数据访问
Context 提供了多种方法来访问 HTTP 请求的数据,包括路径参数、查询参数、表单数据和 JSON 数据等。
type MyStruct struct {Name string `json:"name"`Age int `json:"age"`
}func Test7(t *testing.T) {r := gin.Default()r.GET("/:name", func(c *gin.Context) {// 获取路径参数name := c.Param("name")// 获取查询参数page := c.DefaultQuery("page", "0") // 带默认值// 获取表单参数message := c.PostForm("message")// 将请求body中的 JSON 数据 解析到结构体中var jsonData MyStructif err := c.ShouldBindJSON(&jsonData); err != nil {c.JSON(400, gin.H{"error": err.Error()}) // 如果解析错误,则返回400报错return}println("调用了地址:" + c.Request.Host + c.Request.URL.Path)c.JSON(http.StatusOK, gin.H{"name": name,"page": page,"message": message,"jsonData": jsonData,})})r.Run()
}

4.2.2 响应生成
上下文对象提供了一系列方法来构建 HTTP 响应,包括设置状态码、返回 JSON/XML/HTML 等。
func Test8(t *testing.T) {r := gin.Default()group := r.Group("/test_response"){group.GET("string", func(c *gin.Context) {// 返回字符串c.String(200, "string...")})group.GET("json", func(c *gin.Context) {// 返回json格式c.JSON(200, gin.H{"json": "json...",})})// 返回html页面,需要先加载模板r.LoadHTMLGlob("./html/*")group.GET("html", func(c *gin.Context) {c.HTML(200, "index.html", gin.H{"title": "这是个标题。。。",})})}r.Run()
}
项目目录下建html文件夹,里面新建文件index.html,内容为
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>{{ .title }}</title>
</head>
<body><h1>Welcome to {{ .title }}</h1>
</body>
</html>
4.2.3 状态码与头信息
可以通过上下文设置 HTTP 状态码和头信息。
c.Status(200)c.Header("Content-Type", "application/json") // 在使用 Gin 返回 JSON 响应时,c.JSON() 方法会自动将响应的内容类型设置为 application/json,所以通常不用手动设置
4.2.4 流控制与错误处理
支持流控制,比如终止请求链或跳过剩余中间件,还可以进行错误管理。
func Test9(t *testing.T) {r := gin.Default()r.GET("/test_error/:bool", func(c *gin.Context) {param := c.Param("bool")// 如果用户调用的是/test_error/true,则直接返回{ "error": "测试错误" }if param == "true" {c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "测试错误"})return}// 否则才正常返回c.JSON(200, gin.H{"success": "正常返回",})})r.Run()
}
4.2.5 键值存储(Set/Get)
上下文允许在不同处理中传递数据,可以使用键值对存储临时数据。
c.Set("mykey","value")value,_:=c.Get ("mykey")
4.2.6 并发安全性
- Gin 的 Context 是不支持跨 goroutine 使用的,因为它不是线程安全的。如果需要跨 goroutine 使用 Context 中的信息,应该提前将所需的数据提取出来。
- 每个 HTTP 请求都会创建一个新的
Context实例,该实例仅在处理该请求的过程中有效。一旦请求处理完毕,Gin 会回收这个Context对象以供将来的请求使用。因此,在另一个 goroutine 中持有对同一Context的引用可能导致不可预测的问题,因为原始请求可能已经结束。
4.3 Middleware(中间件)
中间件在处理请求的过程中起到拦截和处理的作用,可以在请求到达最终路由之前进行一些操作,比如日志记录、身份验证、跨域资源共享(CORS)、错误恢复等。
注!中间件的概念与Java中的切面(Aspect-Oriented Programming,AOP)在某些方面是像的!
- 定义:中间件是一个函数,它接收
gin.Context作为参数,并通过调用Next()来执行下一个中间件或最终处理器。 - 链式调用:Gin中的中间件采用链式调用方式,多个中间件可以按顺序依次执行。
- 全局与局部:可以将中间件应用于整个应用程序,也可以仅限于特定路由。
4.3.1 默认中间件
Default引擎已经包含了两个默认中间件Logger()和Recovery(),r := gin.Default()源码:
// Default returns an Engine instance with the Logger and Recovery middleware already attached.func Default(opts ...OptionFunc) *Engine {debugPrintWARNINGDefault()engine := New()engine.Use(Logger(), Recovery()) // 配置了两个中间件return engine.With(opts...)}
- gin.Logger()
- 功能:这个中间件用于记录HTTP请求日志,包括请求的路径、方法、状态码、处理时间等信息。
- 使用:通常用于开发和生产环境下的请求日志记录,帮助开发者了解应用程序的运行情况。
- gin.Recovery()
- 功能:这个中间件用于从panic(程序崩溃)中恢复,并返回500错误响应。它确保即使发生了未捕获的异常,服务器也不会崩溃。
- 使用:建议在生产环境下始终启用,以提高应用程序的稳定性和可靠性。
4.3.1 全局中间件
全局中间件会对所有请求生效,通常用于通用功能,如日志记录或错误恢复。
通过r.Use()方法使用中间件:
// 使用Logger和Recovery两个默认提供的全局中间件
r.Use(gin.Logger())
r.Use(gin.Recovery())
4.3.2 路由组级别的中间件
可以将某些特定功能限制在某个路由组内,而不是整个应用程序。
func Test10(t *testing.T) {r := gin.Default()group := r.Group("/v1")// 对分组使用一个中间件group.Use(func(context *gin.Context) {fmt.Println("进入分组中间件")})group.GET("/group", func(c *gin.Context) {fmt.Println("group 返回json。。。")c.JSON(200, gin.H{"msg": "success!",})})r.GET("/v2", func(c *gin.Context) {fmt.Println("v2 返回json")c.JSON(200, gin.H{"msg": "success!",})})r.Run()}
输出
进入分组中间件
group 返回json。。。
[GIN] 2024/12/12 - 14:57:16 | 200 | 28.996µs | ::1 | GET "/v1/group"
v2 返回json
[GIN] 2024/12/12 - 14:57:18 | 200 | 23.899µs | ::1 | GET "/v2"
4.3.3 实现自定义Middleware
自定义Middleware需要实现具体逻辑并返回gin.HandlerFunc类型。以下是一个简单示例:
func MyMiddleware() gin.HandlerFunc {return func(c *gin.Context) {fmt.Println("这是定义函数返回中间件的方式使用中间件")}
}func Test11(t *testing.T) {r := gin.New()r.Use(MyMiddleware())r.Use(func(c *gin.Context) {fmt.Println("这是匿名函数的方式使用中间件")})r.GET("/test", func(c *gin.Context) {fmt.Println("正常返回")})r.Run()
}
输出
这是定义函数返回中间件的方式使用中间件
这是匿名函数的方式使用中间件
正常返回
为什么 Golang 知道这是一个 HandlerFunc?
Golang 是一种静态类型语言,它通过类型推断和接口匹配机制来判断某个对象是否实现了某个接口或符合某种类型。在 Gin 中,只要你的自定义方法符合上述签名,就会被自动识别为 HandlerFunc 类型。
相关文章:
20 go语言(golang) - gin框架安装及使用(一)
一、简介 Gin是一个用Go语言编写的高性能Web框架,专注于构建快速、可靠的HTTP服务。它以其速度和简洁性而闻名,非常适合用于开发RESTful API。 高性能:Gin使用了httprouter进行路由管理,这是一个轻量级且非常快速的HTTP请求路由器…...
重生之我在学Vue--第3天 Vue 3 模板语法与指令
重生之我在学Vue–第3天 Vue 3 模板语法与指令 文章目录 重生之我在学Vue--第3天 Vue 3 模板语法与指令前言一、数据绑定1.1 单向绑定1.2 双向绑定 二、常用指令2.1 v-bind2.2 v-model2.3 v-if2.4 v-show2.5 v-for2.6 v-on 三、事件处理与表单绑定3.1 事件处理3.2 表单绑定 前言…...
电脑win11家庭版升级专业版和企业版相关事项
我的是零刻ser9,自带win11家庭版,但是我有远程操控需求,想用windows系统自带的远程连接功能,所以需要升级为专业版。然后在系统激活页面通过更改序列号方式,淘宝几块钱买了个序列号升级成功专业版了。但是,…...
docker 架构详解
Docker架构是基于客户端-服务器(C/S)模式的,包含多个关键组件,以确保容器化应用的高效构建、管理和运行。以下是对Docker架构的详细解析: Docker 架构概述 Docker 架构采用客户端-服务器(C/S)…...
tinyCam Pro 用于远程监控,控制和录制您的私人公共网络或IP摄像机
tinyCam Pro 是一款用于远程监控,控制和录制您的私人/公共网络或IP摄像机,视频编码器和具有500万次下载的CCTV摄像头的DVR。需使用3G/4G/WiFi连接和下载数据。 tinyCam Monitor Pro 可用于远程安全地监控您的宝宝、宠物、家庭、商业、交通和天气…...
Flask 验证码自动生成
Flask 验证码自动生成 想必验证码大家都有所了解,但是可以自己定义图片验证码,包含数字,英文以及数字计算,自动生成验证码。 生成图片以及结果 from captcha.image import ImageCaptchafrom PIL import Image from random impo…...
vmpwn小总结
前言: 好久没有更新博客了,关于vm的学习也是断断续续的,只见识了几道题目,但是还是想总结一下,所谓vmpwn就是把出栈,进栈,寄存器,bss段等单独申请一块空闲实现相关的功能࿰…...
开源密码管理器 Bitwarden 一站式管理所有密码以及 2FA
本文首发于只抄博客,欢迎点击原文链接了解更多内容。 前言 随着注册的平台越来越多,管理密码的难度也越来越高了。要是把密码都设置成一样的,担心哪天某个平台泄露被一锅端,而每个平台单独一个密码又不太好记,这时候就…...
标准体重计算API集成指南
标准体重计算API集成指南 引言 在当今数字化和健康意识日益增长的时代,开发人员和健康管理专业人士不断寻找创新的方法来促进用户的健康生活。标准体重计算是一个关键的健康指标,它可以帮助个人了解自己的身体状况,并为制定合适的饮食和运动…...
多个终端查看的history不一样,如何确保多个终端会话之间的 history 一致,减少历史记录差异
问题: 在使用 Linux 系统时,history 命令显示的历史记录通常是与当前终端会话相关的。这就意味着,如果你在多个终端中打开会话,它们显示的历史记录可能不完全相同。这个问题通常是由以下原因引起的: 原因:…...
Spring Boot整合EasyExcel并行导出及Zip压缩下载
1. 项目依赖 首先,我们需要引入相关的依赖,包括 Spring Boot 和阿里巴巴的 EasyExcel 组件,此外还需要使用 Java 的 Zip 工具进行压缩操作。 <dependencies><!-- Spring Web --><dependency><groupId>org.springfr…...
Docker 对 iptables 规则的自动配置,这句话是什么意思
Docker 对 iptables 规则的自动配置指的是 Docker 守护进程 (daemon) 会自动管理 Linux 系统上的 iptables 规则,以便容器可以正确地进行网络通信。这对于大多数用户来说是一个方便的功能,因为它简化了容器网络配置。 具体来说,这意味着&…...
使用aarch64-unknown-linux-musl编译生成静态ARM64可执行文件
使用aarch64-unknown-linux-musl编译生成静态ARM64可执行文件 使用aarch64-unknown-linux-musl编译生成静态ARM64可执行文件1. 安装aarch64-unknown-linux-musl目标2. 安装交叉编译工具链安装musl-cross-make 3. 配置Rust编译器使用交叉编译工具链4. 编译你的Rust项目5. 运行或…...
【SpringBoot中出现循环依赖错误】
SpringBoot中出现循环依赖错误 在Spring Boot中,循环依赖(circular dependency)是指两个或多个bean相互依赖,形成一个闭合的依赖环。例如,Bean A依赖于Bean B,而Bean B又反过来依赖于Bean A。这种情况下&a…...
数据仓库-基于角色的权限管理(RBAC)
什么是基于角色的用户管理? 基于角色的用户管理(Role-Based Access Control,简称RBAC)是通过为角色赋予权限,用户通过成为适当的角色而得到这些角色的权限。 角色是一组权限的抽象。 使用RBAC可以极大简化对权限的管理。 什么是RBAC模型&…...
springboot3整合javafx解决bean注入问题
springboot整合javafx时候,很多问题就在于controller没有被spring容器管理,无法注入bean,在这里提供一套自己的解决思路 执行逻辑 这里仅仅提供一个演示,我点击按钮之后,从service层返回一个文本并显示 项目结构 创…...
.NET 8 Blazor Web项目中的 .razor 文件与 .cshtml 文件的本质区别
在.NET 8 Blazor Web项目中,.razor 和 .cshtml 文件是常用的视图文件格式。尽管它们看起来有相似之处,但在使用方式、功能和渲染机制上有着根本的不同。理解它们的本质区别,有助于开发者更好地选择合适的文件格式,并构建符合需求的…...
SpringBoot快速使用
一些名词的碎碎念: 1> 俩种网络应用设计模式 C/S 客户端/服务器 B/S 浏览器/服务器 俩者对比: 2> 集群和分布式的概念 集群: 分布式: 例子: 一个公司有一个人身兼多职 集群: 招聘N个和上面这个人一样身兼多职 分布式: 招聘N个人,分担上面这个人的工作,进行工作的拆分. 工…...
【C语言实现:用队列模拟栈与用栈模拟队列(LeetCode 225 232)】
LeetCode刷题记录 🌐 我的博客主页:iiiiiankor🎯 如果你觉得我的内容对你有帮助,不妨点个赞👍、留个评论✍,或者收藏⭐,让我们一起进步!📝 专栏系列:LeetCode…...
远程控制软件对比与使用推荐
远程控制软件对比与使用推荐 远程控制软件在现代工作环境中扮演着重要角色,无论是远程办公、技术支持、还是家庭成员之间的协助。以下是对几种常见远程控制软件的详细对比和推荐使用场景。 1. TeamViewer 特点 跨平台:支持Windows、macOS、Linux、iO…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
git: early EOF
macOS报错: Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...
何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡
何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡 背景 我们以建设星云智控官网来做AI编程实践,很多人以为AI已经强大到不需要程序员了,其实不是,AI更加需要程序员,普通人…...
6.计算机网络核心知识点精要手册
计算机网络核心知识点精要手册 1.协议基础篇 网络协议三要素 语法:数据与控制信息的结构或格式,如同语言中的语法规则语义:控制信息的具体含义和响应方式,规定通信双方"说什么"同步:事件执行的顺序与时序…...
