一、响应字符串和 JSON
Go
package main
import "github.com/gin-gonic/gin"
// 字符串
func _string(c *gin.Context) {
c.String(200, "nihao")
}
// json
func _json(c *gin.Context) {
// 结构体
type Userinfo struct {
Username string `json:"user_name"`
Age int `json:"age"`
Password string `json:"-"` // - 忽略转化为json
}
//user := Userinfo{"nsaf", 23, "123456"}
// map
//userMap := map[string]interface{}{
// "user_name": "dongdong",
// "age": 23,
//}
// 直接响应json
// user 可以是任意类型, c.JSON 内部调用的是 json.Marshal
c.JSON(200, gin.H{"username": "dongodng", "age": 20})
}
func main() {
r := gin.Default()
r.GET("/", _string)
r.GET("json", _json)
r.Run(":80")
}
二、响应XML和yaml
null
package main
import "github.com/gin-gonic/gin"
// xml
func _xml(c *gin.Context) {
c.XML(200, gin.H{"user": "hanru", "message": "satatus", "status": 200, "data": gin.H{"user": "feng"}})
}
// yaml
func _yaml(c *gin.Context) {
c.XML(200, gin.H{"user": "hanru", "message": "satatus", "status": 200, "data": gin.H{"user": "feng"}})
}
func main() {
r := gin.Default()
r.GET("/", _xml)
r.GET("json", _yaml)
r.Run(":80")
}
三、响应html
null
package main
import "github.com/gin-gonic/gin"
func _html(c *gin.Context) {
type User struct {
Username string
Age int
}
user := User{"dongdong", 20}
c.HTML(200, "index.html", user)
}
func main() {
r := gin.Default()
// 加载模版目录下所有文件
r.LoadHTMLGlob("template/*")
r.GET("/", _html)
r.Run(":80")
}
-
加载模版文件有三种方法
在 Gin 框架中,
LoadHTMLGlob、LoadHTMLFiles和LoadHTMLFS这三个方法的作用完全一致 :都是将 HTML 模板文件加载到 Gin 的模板引擎中 ,以便后续通过c.HTML()方法进行渲染。它们的区别仅仅在于指定模板文件的方式不同,以适应不同的项目结构和部署需求。下面是每个方法的详细作用说明:
1.
r.LoadHTMLGlob(pattern string)-
作用 :使用 glob 通配符模式 (如
*、**)批量加载匹配的模板文件。 -
特点:
-
代码最简洁,适合模板文件集中在某个目录(或嵌套子目录)的场景。
-
支持
**匹配多级子目录,例如"templates/**/*"。 -
无法精确控制单个文件,匹配到的所有文件都会被加载。
-
-
常见用法:
// 加载 templates 目录下的所有 .html 文件(不包含子目录) r.LoadHTMLGlob("templates/*.html") // 加载 templates 及其所有子目录下的 .html 文件 r.LoadHTMLGlob("templates/**/*.html")
2.
r.LoadHTMLFiles(filenames ...string)-
作用 :显式枚举一个或多个模板文件的路径,逐个添加。
-
特点:
-
精确控制加载哪些文件,不会多加载、也不会少加载。
-
当模板文件数量很少,或者需要排除某些文件时非常方便。
-
项目变大后,枚举列表会变得冗长且难以维护。
-
-
常见用法:
r.LoadHTMLFiles("templates/index.html", "templates/user.html", "templates/error.html")
3.
r.LoadHTMLFS(fs http.FileSystem)-
作用 :从一个实现了
http.FileSystem接口的文件系统中加载所有模板文件。 -
特点:
-
Go 1.16+ 引入,常与
embed包配合使用,将模板文件编译进二进制程序。 -
部署时无需外挂模板目录,一个二进制文件即可运行。
-
加载的规则是扫描整个文件系统(类似
LoadHTMLGlob扫描磁盘目录),但文件来源是内存中的虚拟文件系统。
-
-
常见用法:
Go//go:embed templates/* var templateFS embed.FS func main() { r := gin.Default() r.LoadHTMLFS(http.FS(templateFS)) // 之后就可以正常使用 c.HTML() 渲染 templates 目录下的模板 }
总结一句话
-
LoadHTMLGlob→ 用通配符模式批量加(最常用) -
LoadHTMLFiles→ 用手工列表精确加(适合少量文件) -
LoadHTMLFS→ 用虚拟文件系统加(适合嵌入部署)
三者选其一即可,不要重复调用(后调用的会覆盖之前加载的模板)。根据你的项目是开发期还是生产部署、模板数量多少、是否需要单文件发布,选择最合适的方法即可。
-
-
c.HTML()- 是 Gin 框架中用于渲染并返回 HTML 响应的核心方法。它的作用是将指定的 HTML 模板文件与动态数据结合,生成最终的 HTML 页面,并通过 HTTP 响应发送给客户端(通常是浏览器)。
简单来说:它让你能够用动态数据填充 HTML 模板,生成完整的网页返回给用户。
函数签名
c.HTML(code int, name string, obj any)-
code:HTTP 状态码,如200(成功)、404(未找到)等。 -
name:模板文件的名称(通常是在LoadHTMLGlob等方法中加载的模板文件名,如"index.html")。 -
obj:传递给模板的数据,可以是任何 Go 类型(结构体、map、切片等),模板中用{``{.字段名}}访问。
工作原理
-
模板加载 :必须先通过
r.LoadHTMLGlob()、r.LoadHTMLFiles()或r.LoadHTMLFS()将模板文件加载到 Gin 的模板引擎中。 -
模板渲染 :调用
c.HTML()时,Gin 会根据name找到对应的模板,并用obj提供的数据填充模板中的占位符(如{``{.Title}})。 -
响应发送 :渲染完成后,Gin 会将生成的 HTML 字符串作为响应体,连同指定的
code状态码一起发送给客户端。
四、文件响应
null
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func _html(c *gin.Context) {
type User struct {
Username string
Age int
}
user := User{"dongdong", 20}
c.HTML(200, "index.html", user)
}
func main() {
r := gin.Default()
// 加载模版目录下所有文件
r.LoadHTMLGlob("template/*")
// 配置单个文件,网页请求的路由,文件的路径
r.StaticFile("/gif/", "static/jiemi.gif")
// 网页请求这个静态目录的前缀,第二个参数是一个目录
r.StaticFS("/static/", http.Dir("static/static/"))
r.GET("/", _html)
r.Run(":80")
}
在 Gin 框架中,处理静态文件的核心方法有四个,分别是
router.Static、router.StaticFS和router.StaticFile、router.StaticFileFS。它们的主要区别体现在服务的颗粒度和文件来源上。为了方便你直观对比,我将它们的核心区别整理成了下面的表格:
下面我们来逐一说明它们的具体使用方式和适用场景。
其实,Gin 处理静态文件的核心方法主要有三个,而
StaticFileFS可以看作是其中一位的特殊版本。为了方便你直观对比,我把它们的核心区别整理成了下面的表格:
| 方法 | 服务颗粒度 | 文件来源 | 主要用途 |
|---|---|---|---|
router.Static |
整个目录 | 本地文件系统路径 | 开发环境,或生产环境提供本地静态资源目录 |
router.StaticFS |
整个目录 | 实现了 http.FileSystem 接口的对象 |
生产环境,需要精细控制文件解析,或从嵌入式文件系统提供整个静态资源目录 |
router.StaticFile |
单个文件 | 本地文件系统路径 | 提供 favicon.ico、robots.txt 这类特定的单文件 |
router.StaticFileFS |
单个文件 | 实现了 http.FileSystem 接口的对象 |
需要从嵌入式文件系统 提供特定单文件,例如打包后的 favicon.ico |
router.Static:服务本地静态资源目录这是最直接、最常用的静态文件服务方法。它接收一个
relativePath(URL中的路径前缀)和一个root(服务器上的实际目录路径),然后将所有对这个URL前缀的请求,映射到对应的本地目录上。
典型用法:
null
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
// 将 URL 路径 /static 映射到本地目录 ./public
// 此时,请求 GET /static/css/style.css 将返回 ./public/css/style.css 文件
r.Static("/static", "./public")
// 你也可以为不同的 URL 前缀映射不同的本地目录
r.Static("/images", "./assets/images")
r.Run(":8080")
}
适用场景: 绝大多数开发和生产场景。这是Gin推荐的、用于服务一个本地文件夹内所有静态资源的标准方法。
router.StaticFS:更灵活地控制文件系统与
router.Static相比,router.StaticFS的第二个参数不再是一个文件路径字符串,而是一个http.FileSystem接口。这意味着你可以传入任何实现了这个接口的对象,而不仅仅是一个本地文件夹路径。这个接口是 Go 标准库
net/http的一部分,Gin 的router.Static方法内部实际上也是通过http.Dir将文件路径转换为了http.FileSystem。典型用法(服务本地目录):
// 等同于 router.Static("/static", "./public") r.StaticFS("/static", http.Dir("./public"))这段代码与
r.Static("/static", "./public")的效果完全一致,只是实现方式不同。进阶用法:结合
embed打包静态文件 使用router.StaticFS最主要的场景是结合 Go 1.16 引入的embed包,将静态文件直接编译进最终的二进制程序中,实现"零依赖"部署[reference:4]。
null
package main
import (
"embed"
"net/http"
"github.com/gin-gonic/gin"
)
//go:embed public
var staticFiles embed.FS
func main() {
r := gin.Default()
// 将嵌入的文件系统转换为 http.FileSystem 接口
// 然后通过 /static 路径提供服务
r.StaticFS("/static", http.FS(staticFiles))
r.Run(":8080")
}
适用场景: 需要将静态资源打包到二进制文件中(常用于生产环境)[reference:5];或者需要对文件服务行为有更精细的控制,例如自定义目录列表等[reference:6]。
router.StaticFile:服务单个特定文件这个方法不是服务一个目录,而是精准地为单个文件注册一个路由。它接收一个
relativePath(URL路径)和一个filePath(文件在服务器上的实际路径)。
典型用法:
null
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
// 当用户访问 /favicon.ico 时,返回 ./assets/favicon.ico 文件
r.StaticFile("/favicon.ico", "./assets/favicon.ico")
// 为 robots.txt 文件提供服务
r.StaticFile("/robots.txt", "./static/robots.txt")
r.Run(":8080")
}
适用场景: 为根路径下的一些固定文件(如
favicon.ico、robots.txt、sitemap.xml等)提供服务,或者你想将一个特定的文件暴露在一个特殊的 URL 路径下。
router.StaticFileFS
它的作用在于,让你能像
StaticFile一样服务单个文件,但文件的来源可以是内存中的虚拟文件系统,而不必是磁盘上的物理路径。它的核心优势是:
精准服务 :和
StaticFile一样,只为指定的单个文件创建精确的路由。来源灵活 :可以服务于任何实现了
http.FileSystem接口的源,如embed.FS。最经典的用法,是结合
embed将单个静态文件打包进二进制程序。 这对于需要将类似favicon.ico的必备资源一起打包分发,实现"单文件部署"的场景非常有用。
Go
package main
import (
"embed"
"net/http"
"github.com/gin-gonic/gin"
)
//go:embed favicon.ico
var staticFiles embed.FS
func main() {
r := gin.Default()
// 从打包的文件系统中提取 favicon.ico 并为之创建路由
r.StaticFileFS("/favicon.ico", "favicon.ico", http.FS(staticFiles))
r.Run(":8080")
}
总结
所以,这四个方法是相互补充的关系:
如果你需要服务本地磁盘上的整个目录 ,用
router.Static。如果需要服务嵌入式(embed)的整个目录 ,用
router.StaticFS。如果需要服务本地磁盘上的单个文件 ,用
router.StaticFile。如果需要服务嵌入式(embed)的单个文件 ,用
router.StaticFileFS。
五、重定向
null
package main
import (
"github.com/gin-gonic/gin"
)
func _redirect(c *gin.Context) {
c.Redirect(301, "http://www.fengfengzhidao.com")
}
func main() {
r := gin.Default()
r.GET("/redirect", _redirect)
r.Run(":80")
}
在 Gin 框架中,实现重定向非常简单,核心方法是
c.Redirect()。它属于Context对象,用于向客户端发送一个 HTTP 重定向响应。基本用法
Goc.Redirect(http.StatusFound, "/new-path")
第一个参数:HTTP 状态码,表示重定向的类型。
第二个参数:目标 URL(可以是相对路径或绝对路径)。
常用的重定向状态码
| 状态码 | 常量 | 含义 | 使用场景 |
|---|---|---|---|
| 301 | http.StatusMovedPermanently |
永久重定向 | 资源 URL 永久变更,搜索引擎会更新索引 |
| 302 | http.StatusFound |
临时重定向 | 默认推荐,表示本次请求临时跳转,方法可能改变 |
| 303 | http.StatusSeeOther |
参见其他 | POST 后重定向到 GET 结果(PRG 模式) |
| 307 | http.StatusTemporaryRedirect |
临时重定向 | 与 302 类似,但保证请求方法不变 |
| 308 | http.StatusPermanentRedirect |
永久重定向 | 与 301 类似,但保证请求方法不变 |
代码示例
Go
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
// 示例1:访问 /old 临时重定向到 /new
r.GET("/old", func(c *gin.Context) {
c.Redirect(http.StatusFound, "/new")
})
// 示例2:POST 请求后重定向到 GET 结果(PRG 模式)
r.POST("/submit", func(c *gin.Context) {
// 处理表单数据...
c.Redirect(http.StatusSeeOther, "/success")
})
// 示例3:永久重定向到外部站点
r.GET("/google", func(c *gin.Context) {
c.Redirect(http.StatusMovedPermanently, "https://www.google.com")
})
// 目标路由
r.GET("/new", func(c *gin.Context) {
c.String(200, "新的位置")
})
r.GET("/success", func(c *gin.Context) {
c.String(200, "操作成功")
})
r.Run(":8080")
}
重要注意事项
-
调用
Redirect后应立即return,避免后续代码继续执行(虽然 Gin 内部会终止请求处理,但显式return是良好习惯):c.Redirect(302, "/login") return // 可选,但建议加上 -
不要在重定向前写入响应体 。一旦调用了
c.String、c.JSON等方法,再调用Redirect会失败(因为 HTTP 头已经发送)。 -
相对路径 :
Redirect支持相对路径(如"/login")和绝对路径(如"https://example.com")。相对路径基于当前请求的Host和X-Forwarded-Proto等信息由浏览器解析。
小结
使用
c.Redirect(status, url)即可实现重定向。默认使用 302 临时重定向,根据业务需求选择 301、303、307 等。
注意与响应体写入的顺序,以及必要时使用
return避免逻辑混乱。
如果需要更复杂的重定向逻辑(如根据用户角色跳转不同页面),同样可以在 Redirect 前进行判断,然后调用该方法即可。