Gin框架操作指南10:服务器与高级功能
官方文档地址(中文):https://gin-gonic.com/zh-cn/docs/
注:本教程采用工作区机制,所以一个项目下载了Gin框架,其余项目就无需重复下载,想了解的读者可阅读第一节:Gin操作指南:开山篇。
本节演示服务器与高级功能,包括运行多个服务;优雅地重启或停止;重定向;支持Let’s-Encrypt;HTTP2-server推送。在开始之前,我们需要在”06服务器与高级功能“目录下打开命令行,执行如下命令来创建子目录:
mkdir 运行多个服务 优雅地重启或停止 重定向 支持Let's-Encrypt HTTP2-server推送
注意:四五两节需要下载安装openssl或者自己拥有一个域名,本文演示使用openssl的情况,openssl的下载与安装还请读者自行搜索,本站一堆。
目录
- 一、运行多个服务
- 二、优雅地重启或停止
- 三、重定向
- 四、支持Let's-Encrypt
- 五、HTTP2-server推送
一、运行多个服务
首先执行如下命令安装errgroup包
go get golang.org/x/sync/errgroup
然后填充代码
package mainimport ("log" // 引入日志包,用于记录错误"net/http" // 引入HTTP包,用于创建HTTP服务器"time" // 引入时间包,用于设置超时"github.com/gin-gonic/gin" // 引入Gin框架,用于处理HTTP请求"golang.org/x/sync/errgroup" // 引入errgroup包,用于处理并发任务和错误管理
)// 声明一个errgroup.Group类型的变量,用于管理并发任务
var (g errgroup.Group
)// router01 创建第一个HTTP路由
func router01() http.Handler {e := gin.New() // 创建一个新的Gin路由e.Use(gin.Recovery()) // 使用Recovery中间件,防止因panic导致服务崩溃// 定义GET请求的路由处理e.GET("/", func(c *gin.Context) {c.JSON( // 返回JSON格式的响应http.StatusOK, // HTTP状态码200gin.H{ // 返回的数据"code": http.StatusOK, // 返回的状态码"error": "Welcome server 01", // 返回的消息},)})return e // 返回路由
}// router02 创建第二个HTTP路由
func router02() http.Handler {e := gin.New() // 创建一个新的Gin路由e.Use(gin.Recovery()) // 使用Recovery中间件,防止因panic导致服务崩溃// 定义GET请求的路由处理e.GET("/", func(c *gin.Context) {c.JSON( // 返回JSON格式的响应http.StatusOK, // HTTP状态码200gin.H{ // 返回的数据"code": http.StatusOK, // 返回的状态码"error": "Welcome server 02", // 返回的消息},)})return e // 返回路由
}// main函数是程序的入口
func main() {// 创建第一个HTTP服务器,监听8080端口server01 := &http.Server{Addr: ":8080", // 服务器地址和端口Handler: router01(), // 设置处理请求的路由ReadTimeout: 5 * time.Second, // 设置读取超时时间WriteTimeout: 10 * time.Second, // 设置写入超时时间}// 创建第二个HTTP服务器,监听8081端口server02 := &http.Server{Addr: ":8081", // 服务器地址和端口Handler: router02(), // 设置处理请求的路由ReadTimeout: 5 * time.Second, // 设置读取超时时间WriteTimeout: 10 * time.Second, // 设置写入超时时间}// 启动第一个服务器的监听g.Go(func() error {return server01.ListenAndServe() // 启动服务器并监听请求})// 启动第二个服务器的监听g.Go(func() error {return server02.ListenAndServe() // 启动服务器并监听请求})// 等待所有服务器的goroutine完成,如果出错则记录并退出if err := g.Wait(); err != nil {log.Fatal(err) // 记录错误并退出程序}
}
效果

二、优雅地重启或停止
优雅关闭确保在关闭服务器时,正在处理的请求能够完成。这意味着用户不会因为服务器突然停止而遭遇错误,提升用户体验。优雅关闭还允许应用在关闭前执行一些必要的清理操作,例如释放数据库连接、保存缓存、记录日志等,避免数据丢失或资源泄漏。下面演示如何实现。
如果版本低于1.8,可以考虑官方的建议:官方声明。
如果你使用的是 Go 1.8及以上版本,可以使用 http.Server 内置的 Shutdown() 方法优雅地关机:
//go:build go1.8
// +build go1.8package mainimport ("context" // 引入 context 包,用于控制超时和取消操作"log" // 引入 log 包,用于记录日志"net/http" // 引入 net/http 包,用于创建 HTTP 服务器"os" // 引入 os 包,用于与操作系统进行交互"os/signal" // 引入 os/signal 包,用于接收系统信号"time" // 引入 time 包,用于时间相关的操作"github.com/gin-gonic/gin" // 引入 Gin 框架
)func main() {// 创建默认的 Gin 路由router := gin.Default()// 定义根路由处理函数router.GET("/", func(c *gin.Context) {// 模拟处理时间time.Sleep(5 * time.Second)// 返回字符串响应c.String(http.StatusOK, "Welcome Gin Server")})// 创建 HTTP 服务器srv := &http.Server{Addr: ":8080", // 监听地址和端口Handler: router, // 设置处理请求的路由}// 启动服务器监听请求go func() {// 服务连接if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {// 如果服务出现错误且错误不是因为服务器已关闭,记录错误并退出log.Fatalf("listen: %s\n", err)}}()// 等待中断信号以优雅地关闭服务器(设置 5 秒的超时时间)quit := make(chan os.Signal, 1) // 创建接收信号的通道signal.Notify(quit, os.Interrupt) // 监听中断信号<-quit // 阻塞直到收到信号log.Println("Shutdown Server ...") // 输出服务器关闭信息// 设置关闭服务器的上下文,并设置超时时间为 5 秒ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)defer cancel() // 确保在函数退出时取消上下文if err := srv.Shutdown(ctx); err != nil {// 如果服务器关闭时出现错误,记录错误信息log.Fatal("Server Shutdown:", err)}log.Println("Server exiting") // 输出服务器退出信息
}
效果

三、重定向
创建三个目录:get,post,router
1.GET重定向
cd到get目录
package mainimport ("net/http" // 导入 HTTP 包以使用 HTTP 相关功能"github.com/gin-gonic/gin" // 导入 Gin 框架
)func main() {// 创建一个新的 Gin 引擎实例r := gin.Default()// 定义一个 GET 路由,当访问 /test 时触发该处理函数r.GET("/test", func(c *gin.Context) {// 使用 Redirect 方法进行重定向// http.StatusMovedPermanently 表示 HTTP 301 状态码// 第二个参数是目标 URL,这里重定向到 Google 的首页c.Redirect(http.StatusMovedPermanently, "http://www.google.com/")})// 启动 HTTP 服务器,监听在 8080 端口r.Run(":8080")
}
访问localhost:8080/test即可跳转到Google页面
2.POST重定向
cd到post目录
package mainimport ("net/http" // 导入 HTTP 包以使用 HTTP 相关功能"github.com/gin-gonic/gin" // 导入 Gin 框架
)func main() {// 创建一个新的 Gin 引擎实例r := gin.Default()// 定义一个 GET 路由,当访问 /submit 时触发该处理函数r.GET("/submit", func(c *gin.Context) {// 返回一个 HTML 表单form := `<!DOCTYPE html><html><head><title>Submit Form</title></head><body><h1>Submit to Google</h1><form method="POST" action="/submit/do"><input type="submit" value="Submit"></form></body></html>`c.Header("Content-Type", "text/html") // 设置响应的内容类型为 HTMLc.String(http.StatusOK, form) // 返回表单})// 定义一个 POST 路由,当提交表单时触发该处理函数r.POST("/submit/do", func(c *gin.Context) {// 使用 Redirect 方法进行重定向// http.StatusFound 表示 HTTP 302 状态码// 第二个参数是重定向目标 URL,这里重定向到 Googlec.Redirect(http.StatusFound, "http://www.google.com")})// 启动 HTTP 服务器,监听在 8080 端口r.Run(":8080")
}
运行,打开浏览器访问http://localhost:8080/submit,会出现提交页面

点击提交即可跳转到google
3.路由重定向
cd到router目录
package mainimport ("net/http" // 导入 HTTP 包以使用 HTTP 相关功能"github.com/gin-gonic/gin" // 导入 Gin 框架
)func main() {// 创建一个新的 Gin 引擎实例r := gin.Default()// 定义一个 GET 路由,当访问 /test 时触发该处理函数r.GET("/test", func(c *gin.Context) {// 修改请求的 URL 路径,将其重定向到 /test2c.Request.URL.Path = "/test2"// 调用 r.HandleContext 方法,重新处理上下文// 这会根据新的 URL 路径找到对应的处理函数r.HandleContext(c)})// 定义一个 GET 路由,当访问 /test2 时触发该处理函数r.GET("/test2", func(c *gin.Context) {// 返回 JSON 响应,状态码为 200,内容为 {"hello": "world"}c.JSON(http.StatusOK, gin.H{"hello": "world"})})// 启动 HTTP 服务器,监听在 8080 端口r.Run(":8080")
}

注意,因为这次的路由路径还是和之前一样,所以如果你的浏览器再次跳转到google,清下cookie或把代码中的路由路径改下就行了。
四、支持Let’s-Encrypt
package mainimport ("log""net/http" // 导入 HTTP 包以使用 HTTP 相关功能"github.com/gin-gonic/gin" // 导入 Gin 框架
)func main() {// 创建一个新的 Gin 引擎实例r := gin.Default()// 定义一个 Ping 路由,返回 "pong"r.GET("/ping", func(c *gin.Context) {c.String(http.StatusOK, "pong")})// 启动 HTTPS 服务器,监听在 443 端口err := r.RunTLS(":443", "cert.pem", "key.pem")if err != nil {log.Fatal("Failed to run server: ", err)}
}
执行openssl命令,创建自签名证书
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes
以下是对该命令的解释
-x509: 生成一个自签名的证书。
-newkey rsa:2048: 创建一个新的 RSA 密钥,长度为 2048 位。
-keyout key.pem: 指定生成的私钥文件名。
-out cert.pem: 指定生成的证书文件名。
-days 365: 指定证书有效期为 365 天。
-nodes: 生成的私钥不使用密码保护(不需要输入密码)。
在命令执行过程中,会提示你输入一些信息,如国家、组织名称等,直接按回车跳过即可。
打开浏览器,以谷歌浏览器为例,访问https://localhost/ping,然后按下图操作



五、HTTP2-server推送
在“HTTP2-server推送”目录下新建目录testdata,并执行如下ssl命令,然后和上一节一样,一直按回车即可
openssl req -x509 -newkey rsa:2048 -keyout ./testdata/server.key -out ./testdata/server.pem -days 365 -nodes
新建main.go,填充代码
package mainimport ("html/template" // 导入模板包以处理 HTML 模板"log" // 导入日志包以记录错误信息"github.com/gin-gonic/gin" // 导入 Gin 框架
)// 定义一个 HTML 模板
var html = template.Must(template.New("https").Parse(`
<html>
<head><title>Https Test</title><script src="/assets/app.js"></script> <!-- 引入 JavaScript 文件 -->
</head>
<body><h1 style="color:red;">Welcome, Ginner!</h1> <!-- 欢迎信息 -->
</body>
</html>
`))func main() {// 创建一个新的 Gin 引擎实例r := gin.Default()// 设置静态文件目录,允许访问 /assets 路径r.Static("/assets", "./assets")// 设置 HTML 模板r.SetHTMLTemplate(html)// 定义一个 GET 路由,当访问根路径时触发该处理函数r.GET("/", func(c *gin.Context) {// 检查是否支持 HTTP/2 Server Pushif pusher := c.Writer.Pusher(); pusher != nil {// 使用 pusher.Push() 进行服务器推送if err := pusher.Push("/assets/app.js", nil); err != nil {log.Printf("Failed to push: %v", err) // 如果推送失败,记录错误}}// 渲染 HTML 模板并返回给客户端c.HTML(200, "https", gin.H{"status": "success", // 返回状态})})// 监听并在 https://127.0.0.1:8080 上启动服务// 指定 SSL 证书和私钥的路径r.RunTLS(":8080", "./testdata/server.pem", "./testdata/server.key")
}
效果
访问https://127.0.0.1:8080/,然后步骤和第四节一样,最终返回如下页面

这里说明一下为什么要访问https://127.0.0.1:8080/而不是https://loaclhost:8080/:
虽然我们前面创建证书时是没有填写字段的,但127.0.0.1 是一种特殊的地址,即回环地址(127.0.0.0 到 127.255.255.255 ),这是系统保留用于本地主机通信的地址,即总是指向本机的地址,所以浏览器不管什么情况都会允许连接,显示警告是因为证书要求。相比之下,localhost 作为主机名,必须匹配证书,浏览器才会允许链接,所以当你访问localhost时,浏览器会显示无法访问此网站。
相关文章:
Gin框架操作指南10:服务器与高级功能
官方文档地址(中文):https://gin-gonic.com/zh-cn/docs/ 注:本教程采用工作区机制,所以一个项目下载了Gin框架,其余项目就无需重复下载,想了解的读者可阅读第一节:Gin操作指南&#…...
AIGC技术的学习 系列一
文章目录 前言一、AIGC技术演进1.1 图像视频生成1.2. 文本生成1.3. 多模态生成1.4. 小结二、CAD&CAE软件介绍2.1. CAD软件2.2. CAE软件2.3. 小结三、AIGC技术与CAD&CAE软件的集成案例3.1. 土建设计领域3.2. 机械设计领域四、结语五、参考文献总结前言 在全球智能制造的…...
Milvus×Dify半小时轻松构建RAG系统
最近,检索增强生成(RAG)技术在AI界引起了广泛关注。作为一种将知识库与生成模型结合的新型架构,RAG大大提升了AI应用的实际表现。而在构建RAG系统时,Milvus作为业界领先的开源向量数据库,扮演着关键角色。本…...
wireshark 解密浏览器https数据包
一、导出浏览器证书有两种方法 1、在浏览器快捷方式追加启动参数: --ssl-key-log-file"d:\log\2.log" C:\Users\Administrator\AppData\Local\Google\Chrome\Application\chrome.exe --ssl-key-log-file"d:\log\2.log" 2、环境变量中新建用…...
【HTML】构建网页的基石
我的主页:2的n次方_ HTML 是一种超文本标记语言,不仅有文本,还能包含图片,音频等 1. HTML 的文件基本结构 html 标签是整个 html 文件的最顶层标签,head 标签中写页面的属性,body 标签是页面中显示的…...
rust不允许在全局区定义普通变量!
文章目录 C 中的全局变量Rust 中的全局变量设计哲学的体现 在 C 和 Rust 中,全局变量的处理方式体现了这两种语言设计哲学上的一些根本性差异: C 中的全局变量 C 允许在全局作用域中定义变量。这些变量在程序的整个生命周期内都存在,从程序开…...
量化投资中的数据驱动决策:大数据如何改变金融市场
随着科技的进步,金融行业迎来了前所未有的变革,量化投资作为其中的代表,逐渐成为投资市场的主流。量化投资是基于数学模型、数据分析以及算法策略的投资方式,与传统依赖经验和直觉的投资方法相比,它的核心优势在于能够…...
MySQL 设计数据表
一个数据表主要包含信息有 : 表名、主键、字段、数据类型、索引,本节主要介绍表的命名规范、字段命名、字段的数据类型选择。 新建的表都是新建在 “item_name” 数据库中的,新建 “item_name” 数据库命令如下 : CREATE DATABASE item_name;新建数据库…...
【大数据技术基础 | 实验一】配置SSH免密登录
文章目录 一、实验目的二、实验要求三、实验原理(一)大数据实验一体机(二)SSH免密认证 四、实验环境五、实验内容和步骤(一)搭建集群服务器(二)添加域名映射(三ÿ…...
地级市碳排放效率测算2006-2021年
为了测算碳排放效率,研究者们采用了多种方法,其中超效率SBM(Slack-Based Measure)和超效率CCR(Charnes, Cooper and Rhodes)模型是常用的两种方法。这些模型可以有效地评估决策单元的相对有效性,…...
周易解读:四象
四 象 在前面呢,我是讲完了太极与两仪的知识。这一节,我们来讲解四象的内容。 关于四象的知识,它在正式的周易的经文里面,它并没有多少用处。但是呢,在基础知识的学习里面,四象的知识,大家是…...
Java设计模式梳理:行为型模式(策略,观察者等)
行为型模式 行为型模式关注的是各个类之间的相互作用,将职责划分清楚,使得我们的代码更加地清晰。 策略模式 策略模式太常用了,所以把它放到最前面进行介绍。它比较简单,我就不废话,直接用代码说事吧。 下面设计的…...
【MySQL】入门篇—基本数据类型:使用LIMIT限制结果集
为了提高查询效率和用户体验,MySQL提供了LIMIT子句,用于限制查询结果的行数。LIMIT不仅可以提高性能,还可以帮助用户快速获取所需的数据,尤其在分页显示数据时非常有用。 应用场景: 分页显示:在网页应用中…...
PostgreSQL与MySQL在语法上的区别
PostgreSQL与MySQL在语法上的区别 在数据库管理系统中,PostgreSQL和MySQL都是非常受欢迎的选择。虽然它们都是一种关系型数据库管理系统(RDBMS),但它们在语法上有一些显著的区别。本文将介绍PostgreSQL和MySQL在语法上的主要区别。 数据类型 PostgreS…...
frameworks 之InputDispatcher
frameworks 之InputDispatcher 1. 填充Iq2.进入循环3.进入oq4. 发布消息,并将数据放进去wq5. 接收消息6. 移除wq android 输入事件 主要分 2个流程 事件读取 和 事件分发。本文讲解事件分发流程。 涉及到的类如下 -frameworks/native/services/inputflinger/Input…...
ESP32-IDF GPIO 专题
目录 一、基本介绍1、配置结构体2、API2.1 gpio_config2.2 gpio_reset_pin2.3 gpio_set_intr_type2.4 gpio_intr_enable2.5 gpio_intr_disable2.6 gpio_set_level2.7 gpio_get_level2.8 gpio_set_direction2.9 gpio_set_pull_mode2.10 gpio_isr_register2.11 gpio_install_isr_…...
深度学习代码学习笔记2
1、torch.max correct 0 total 0 for xb,yb in valid_dl:outputs model(xb)_,predicted torch.max(outputs.data,1)total yb.size(0) #yb.size(0) 返回的是张量 yb 在第 0 维的大小,也就是 yb 中的样本数量。correct (predicted yb).sum().item() print(…...
016集——c# 实现CAD类库 与窗体的交互(CAD—C#二次开发入门)
第一步:搭建CAD类库dll开发环境。 第二步:添加窗体 第三步:添加控件 第四步:双击控件,在控件点击方法内输入代码 第五步:在主程序内实例化新建的form类,并弹窗form窗体 第六步:CAD命…...
【亲测可行】最新ubuntu搭建rknn-toolkit2
文章目录 🌕结构图(ONNX->RKNN)🌕下载rknn-toolkit2🌕搭建环境🌙配置镜像源🌙conda搭建python3.8版本的虚拟环境🌙进入packages目录安装依赖库🌕测试安装是否成功🌕其它🌙rknn-toolkit2🌙rknn_model_zoo🌙关于部署的博客发布本文的时间为2024.10.13…...
pico+Unity交互开发——触碰抓取
一、VR交互的类型 Hover(悬停) 定义:发起交互的对象停留在可交互对象的交互区域。例如,当手触摸到物品表面(可交互区域)时,视为触发了Hover。 Grab(抓取) 概念ÿ…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...
pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...
