Gin学习
一、Gin导入与基础使用预览 1、安装Gin框架 1 go get -u github.com/gin-gonic/gin
Gin 使用 encoding/json
作为默认的 json 包,但是你可以在编译中使用标签将其修改为 jsoniter 。
1 $ go build -tags=jsoniter .
2、创建第一个Gin应用 1 2 3 4 5 6 7 8 9 10 11 12 package mainimport "github.com/gin-gonic/gin" func main () { r := gin.New() r.GET("/" , func (c *gin.Context) { c.String(200 , "Hello, Gin!" ) }) r.Run(":8080" ) }
在上面的代码中,我们首先导入了Gin框架的包,然后创建了一个默认的Gin引擎,并定义了一个路由,最后启动了Gin应用程序。
3、常用功能 除了基本的路由功能外,Gin框架还提供了许多常用的功能,如中间件、参数解析、日志记录等。下面是一个使用中间件和参数解析的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package mainimport ( "github.com/gin-gonic/gin" "net/http" ) func main () { r := gin.New() r.Use(gin.Logger()) r.Use(gin.Recovery()) r.GET("/hello" , func (c *gin.Context) { name := c.Query("name" ) c.JSON(http.StatusOK, gin.H{"message" : "Hello, " + name}) }) r.Run(":8080" ) }
在上面的示例中,我们首先使用了Logger和Recovery中间件,然后定义了一个带有参数解析的路由,最后启动了Gin应用程序。
4、路由定义和处理: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 package main import ( "github.com/gin-gonic/gin" ) func main() { router := gin.Default() // GET 请求处理 router.GET("/hello", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "Hello, World!", }) }) // POST 请求处理 router.POST("/users", func(c *gin.Context) { var user User if err := c.ShouldBindJSON(&user); err != nil { c.JSON(400, gin.H{ "error": err.Error(), }) return } // 处理接收到的用户数据 // ... c.JSON(200, gin.H{ "message": "User created successfully", }) }) router.Run(":8080") }
5、参数化路由和路由组: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 package mainimport ( "github.com/gin-gonic/gin" ) func main () { router := gin.Default() router.GET("/users/:id" , func (c *gin.Context) { id := c.Param("id" ) c.String(200 , "User ID: %s" , id) }) v1 := router.Group("/api/v1" ) { v1.GET("/users" , func (c *gin.Context) { c.String(200 , "List of users" ) }) v1.POST("/users" , func (c *gin.Context) { c.String(200 , "Create a user" ) }) v1.PUT("/users/:id" , func (c *gin.Context) { id := c.Param("id" ) c.String(200 , "Update user with ID: %s" , id) }) v1.DELETE("/users/:id" , func (c *gin.Context) { id := c.Param("id" ) c.String(200 , "Delete user with ID: %s" , id) }) } router.Run(":8080" ) }
这些代码示例展示了如何使用 Gin 框架定义路由和处理请求,包括 GET 和 POST 请求的处理、参数化路由以及路由组的使用。
6、模板渲染和静态文件 1. 模板渲染: Gin 框架内置了对多种模板引擎的支持,包括 HTML 模板引擎、Ace 模板引擎等。你可以通过 gin.Default()
方法创建一个默认的路由组,并使用 LoadHTMLGlob
或者 LoadHTMLFiles()
方法来加载模板文件。以下是一个简单的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package mainimport ( "github.com/gin-gonic/gin" "net/http" ) func main () { router := gin.Default() router.LoadHTMLGlob("templates/*" ) router.GET("/hello" , func (c *gin.Context) { c.HTML(http.StatusOK, "hello.tmpl" , gin.H{ "title" : "Hello, Gin!" , }) }) router.Run(":8080" ) }
templates/index.tmpl:
1 2 3 4 5 <html > <h1 > {{ .title }} </h1 > </html >
在这个示例中,我们首先使用 LoadHTMLGlob
方法加载了位于 “templates” 目录下的所有模板文件。然后,在 “/hello” 路由处理函数中,我们使用 c.HTML
方法渲染了名为 “hello.tmpl” 的模板,并传递了一个包含标题信息的数据。
使用不同目录下名称相同的模板:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 func main () { router := gin.Default() router.LoadHTMLGlob("templates/**/*" ) router.GET("/posts/index" , func (c *gin.Context) { c.HTML(http.StatusOK, "posts/index.tmpl" , gin.H{ "title" : "Posts" , }) }) router.GET("/users/index" , func (c *gin.Context) { c.HTML(http.StatusOK, "users/index.tmpl" , gin.H{ "title" : "Users" , }) }) router.Run(":8080" ) }
templates/posts/index.tmpl
1 2 3 4 5 6 7 {{ define "posts/index.tmpl" }} <html > <h1 > {{ .title }} </h1 > <p > Using posts/index.tmpl</p > </html > {{ end }}
templates/users/index.tmpl
1 2 3 4 5 6 7 {{ define "users/index.tmpl" }} <html > <h1 > {{ .title }} </h1 > <p > Using users/index.tmpl</p > </html > {{ end }}
2. 自定义模板渲染器 可以使用自定义的 html 模板渲染
1 2 3 4 5 6 7 8 import "html/template" func main () { router := gin.Default() html := template.Must(template.ParseFiles("file1" , "file2" )) router.SetHTMLTemplate(html) router.Run(":8080" ) }
3. 自定义分隔符 你可以使用自定义分隔
1 2 3 router := gin.Default() router.Delims("{[{" , "}]}" ) router.LoadHTMLGlob("/path/to/templates" )
4. 自定义模板功能 查看详细示例代码 。
main.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import ( "fmt" "html/template" "net/http" "time" "github.com/gin-gonic/gin" ) func formatAsDate (t time.Time) string { year, month, day := t.Date() return fmt.Sprintf("%d/%02d/%02d" , year, month, day) } func main () { router := gin.Default() router.Delims("{[{" , "}]}" ) router.SetFuncMap(template.FuncMap{ "formatAsDate" : formatAsDate, }) router.LoadHTMLFiles("./testdata/template/raw.tmpl" ) router.GET("/raw" , func (c *gin.Context) { c.HTML(http.StatusOK, "raw.tmpl" , map [string ]interface {}{ "now" : time.Date(2017 , 07 , 01 , 0 , 0 , 0 , 0 , time.UTC), }) }) router.Run(":8080" ) }
raw.tmpl
1 Date: {[{.now | formatAsDate}]}
结果:
5. 静态文件服务: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package mainimport "github.com/gin-gonic/gin" func main () { router := gin.Default() router.Static("/static" , "./assets" ) router.StaticFS("/static2" , http.Dir("/tmp" )) router.StaticFile("/favicon.ico" , "./resources/favicon.ico" ) router.Run(":8080" ) }
这个示例展示了如何在 Gin 框架中提供静态文件服务,可以方便地将静态资源文件(如图片、样式表、脚本等)提供给客户端。
7、 JSON 解析与绑定: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package mainimport ( "github.com/gin-gonic/gin" ) type User struct { Username string `json:"username"` Password string `json:"password"` } func main () { router := gin.Default() router.POST("/login" , func (c *gin.Context) { var user User if err := c.ShouldBindJSON(&user); err != nil { c.JSON(400 , gin.H{"error" : err.Error()}) return } c.JSON(200 , gin.H{"message" : "Login successful" }) }) router.Run(":8080" ) }
这个示例演示了如何接收 JSON 格式的请求体,并将其绑定到结构体中进行处理。
这些代码示例展示了 Gin 框架中各种功能的具体使用方法,包括中间件、JSON 解析与绑定等。
8、错误处理和日志记录 1. 自定义错误处理函数 Gin 框架允许你注册全局的中间件来处理错误。你可以创建一个中间件函数来捕获处理程序中的错误,并返回自定义的错误响应。以下是一个简单的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package mainimport ( "github.com/gin-gonic/gin" "net/http" ) func main () { router := gin.Default() router.Use(func (c *gin.Context) { c.Next() if len (c.Errors) > 0 { c.JSON(http.StatusInternalServerError, gin.H{"error" : "服务器内部错误" }) } }) router.GET("/ping" , func (c *gin.Context) { c.Error(gin.Error{Err: errors.New("处理过程中发生错误" )}) }) router.Run(":8080" ) }
在这个示例中,我们创建了一个全局中间件函数来检查处理过程中是否有错误发生,如果有错误则返回自定义的错误响应。在路由处理函数中,我们通过 c.Error
方法模拟了一个处理过程中发生的错误。
2. 使用 Gin 框架的日志功能 Gin 框架默认集成了日志功能,你可以直接使用 gin.Default()
方法创建的默认路由组来记录日志。以下是一个示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package mainimport ( "github.com/gin-gonic/gin" "os" ) func main () { f, _ := os.Create("gin.log" ) gin.DefaultWriter = io.MultiWriter(f, os.Stdout) router := gin.Default() router.GET("/ping" , func (c *gin.Context) { c.String(http.StatusOK, "pong" ) }) router.Run(":8080" ) }
在这个示例中,我们将日志输出到文件 “gin.log” 中,并使用 io.MultiWriter
来同时输出到文件和标准输出。Gin 框架会自动记录请求的详细信息以及处理时间等日志内容。
9、设置当前环境 Gin 项目的部署可以通过环境变量或直接在代码中进行配置。
以下环境变量可用于配置 Gin:
环境变量
说明
PORT
使用 router.Run()
启动 Gin 服务器时(即不带任何参数)监听的 TCP 端口。
GIN_MODE
可设置为 debug
、release
或 test
。用于管理 Gin 的运行模式,如是否输出调试信息。也可以在代码中使用 gin.SetMode(gin.ReleaseMode)
或 gin.SetMode(gin.TestMode)
来设置。
以下代码可用于配置 Gin:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 router := gin.Default() router.Run() router := gin.Default() router.Run("192.168.1.100:8080" ) router := gin.Default() router.Run(":8080" ) router := gin.Default() router.SetTrustedProxies([]string {"192.168.1.2" })
10、不要信任所有代理 Gin 允许你指定哪些请求头可以保存真实的客户端 IP(如果有的话),以及你信任哪些代理(或直接客户端)可以设置这些请求头。
在你的 gin.Engine
上使用 SetTrustedProxies()
函数来指定可信任的网络地址或网络 CIDR,这些地址的请求头中与客户端 IP 相关的信息将被信任。它们可以是 IPv4 地址、IPv4 CIDR、IPv6 地址或 IPv6 CIDR。
注意: 如果你没有使用上述函数指定可信代理,Gin 默认会信任所有代理,这并不安全 。同时,如果你不使用任何代理,可以通过 Engine.SetTrustedProxies(nil)
来禁用此功能,这样 Context.ClientIP()
将直接返回远程地址,避免不必要的计算。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import ( "fmt" "github.com/gin-gonic/gin" ) func main () { router := gin.Default() router.SetTrustedProxies([]string {"192.168.1.2" }) router.GET("/" , func (c *gin.Context) { fmt.Printf("ClientIP: %s\n" , c.ClientIP()) }) router.Run() }
提示: 如果你使用 CDN 服务,可以设置 Engine.TrustedPlatform
来跳过 TrustedProxies 检查,它的优先级高于 TrustedProxies。 请看下面的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import ( "fmt" "github.com/gin-gonic/gin" ) func main () { router := gin.Default() router.TrustedPlatform = gin.PlatformGoogleAppEngine router.TrustedPlatform = gin.PlatformCloudflare router.TrustedPlatform = gin.PlatformFlyIO router.TrustedPlatform = "X-CDN-Client-IP" router.GET("/" , func (c *gin.Context) { fmt.Printf("ClientIP: %s\n" , c.ClientIP()) }) router.Run() }