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(抓取) 概念ÿ…...
解锁桌面音乐新体验:LyricsX让你的Mac成为私人KTV
解锁桌面音乐新体验:LyricsX让你的Mac成为私人KTV 【免费下载链接】Lyrics Swift-based iTunes plug-in to display lyrics on the desktop. 项目地址: https://gitcode.com/gh_mirrors/lyr/Lyrics 还在为听歌时找不到歌词而烦恼吗?LyricsX这款基…...
Fun-ASR-MLT-Nano-2512在教育培训场景的应用:语音课件自动转写
Fun-ASR-MLT-Nano-2512在教育培训场景的应用:语音课件自动转写 1. 技术背景与教育痛点 1.1 教育培训行业的语音处理需求 教育培训行业每天产生大量语音内容,包括教师授课录音、在线课程音频、学生互动语音等。传统的人工转写方式面临三大核心痛点&…...
造相 Z-Image镜像使用指南:显存监控条预警机制与OOM防护策略
造相 Z-Image镜像使用指南:显存监控条预警机制与OOM防护策略 1. 引言:为什么你的AI绘画服务总崩溃? 如果你用过一些开源的文生图模型,大概率遇到过这种情况:兴致勃勃地输入一段描述,点击生成,…...
基于RIME-CNN-LSSVM回归模型的优化与预测应用——以MATLAB环境为例
RIME-CNN-LSSVM回归 基于霜冰优化算法优化卷积神经网络(CNN)结合最小二乘向量机(LSSVM)的数据回归预测(可以更换为分类/单、多变量时序预测/回归,前私我),Matlab代码,可直接运行,适合小白新手 程序已经调试好,无需更改…...
Qwen3-ForcedAligner-0.6B入门必看:start_time为0.00s的边界条件处理
Qwen3-ForcedAligner-0.6B入门必看:start_time为0.00s的边界条件处理 1. 为什么需要关注边界条件 当你使用Qwen3-ForcedAligner-0.6B进行音文对齐时,可能会遇到一个看似简单但很重要的问题:为什么有些词的开始时间是0.00秒?这种…...
Python多解释器不是“未来技术”——它已在金融高频交易系统稳定运行417天(附完整监控看板截图)
第一章:Python多解释器的核心机制与历史演进Python长期以来以全局解释器锁(GIL)为标志性设计,单解释器模型主导了其执行范式。然而,随着多核硬件普及与异步编程兴起,对真正并行执行、内存隔离及轻量级运行时…...
乙巳马年·皇城大门春联生成终端W与低代码平台集成:在Dify中快速创建AI应用
乙巳马年皇城大门春联生成终端W与低代码平台集成:在Dify中快速创建AI应用 又到了岁末年初,很多朋友、商家甚至社区都在为准备春联发愁。传统方式要么自己写,要么找人设计,费时费力不说,风格还未必满意。现在ÿ…...
IndexTTS 2.0情感控制效果:用自然语言描述生成对应语气语音
IndexTTS 2.0情感控制效果:用自然语言描述生成对应语气语音 1. 引言:语音合成的革命性突破 想象一下这样的场景:你正在制作一部动画短片,主角需要说一句"我受够了!"——但你不只是想让它"说出来"…...
VRRP配置里这个‘坑’你踩过吗?详解track监视上行链路与流量黑洞问题
VRRP高可用架构中的隐形陷阱:深度解析上行链路监控与流量黑洞解决方案 当企业核心网络的网关设备突然"失联",但设备状态灯却依然闪烁着健康的绿色,这种看似矛盾的故障场景往往让运维团队陷入困境。上周深夜,某金融公司就…...
TTL与CMOS数字电路核心技术对比分析
1. 数字电路技术解析:TTL与CMOS电路深度对比1.1 数字电路技术发展概述现代数字电子系统的核心构建模块主要采用TTL(Transistor-Transistor Logic)和CMOS(Complementary Metal-Oxide Semiconductor)两种集成电路技术。这两种技术构成了当前数字电路设计的基础&#x…...
