Gin

Gin

  • 下载:go get -u github.com/gin-gonic/gin

  • 导入:import "github.com/gin-gonic/gin"


基本使用

启动服务

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	r := gin.Default()
  // 定义路由
	r.GET("hello", func(c *gin.Context) {
		c.String(http.StatusOK, "hello")
	})
	// r.Run() // 默认监听8080
	r.Run(":8080") // 指定监听端口
}

获取请求信息

// 获取请求对象
request := c.Request

// 获取请求方法信息
// 此方法返回string类型
method := request.Method
fmt.Println(method)

// 获取请求uri信息
// 此方法返回 *url.URL 类型,可以获取URL中的所有信息
var url *url.URL = request.URL
fmt.Println(url)

// 获取请求头信息
// 此方法返回 http.Header 类型,可获取请求头中的所有信息
header := request.Header
fmt.Println(header)

// 获取请求体信息
// 此方法返回 io.ReadCloser 类型,可以从流中读取请求体数据
body := request.Body
fmt.Println(body)

处理不同的请求方法

router.GET("/someGet", getting)
router.POST("/somePost", posting)
router.PUT("/somePut", putting)
router.DELETE("/someDelete", deleting)
router.PATCH("/somePatch", patching)
router.HEAD("/someHead", head)
router.OPTIONS("/someOptions", options)

路径参数

必选的路径参数用:表示,name必须存在,否则不会匹配:

router.GET("/user/:name", func(c *gin.Context) {
  name := c.Param("name")
  c.String(http.StatusOK, "Hello %s", name)
})

可选的路径参数用*表示,可以匹配/user/lisi/user/lisi/play

router.GET("/user/:name/*action", func(c *gin.Context) {
  name := c.Param("name")
  action := c.Param("action")
  message := name + " is " + action
  c.String(http.StatusOK, message)
})

查询参数

router.GET("/welcome", func(c *gin.Context) {
  firstname := c.DefaultQuery("firstname", "Guest")
  lastname := c.Query("lastname") // 等同于 c.Request.URL.Query().Get("lastname")

  c.String(http.StatusOK, "Hello %s %s", firstname, lastname)
})

Multipart/Urlencoded Form 表单处理

router.POST("/form_post", func(c *gin.Context) {
  message := c.PostForm("message") // 获取表单字段,message
  nick := c.DefaultPostForm("nick", "anonymous") // 获取表单字段 nick,并给予缺省值

  c.JSON(200, gin.H{
    "status":  "posted",
    "message": message,
    "nick":    nick,
  })
})

表单/查询参数数据转换map

POST /post?ids[a]=1234&ids[b]=hello HTTP/1.1
Content-Type: application/x-www-form-urlencoded

names[first]=thinkerou&names[second]=tianou
router.POST("/post", func(c *gin.Context) {
  ids := c.QueryMap("ids")
  names := c.PostFormMap("names")

  fmt.Printf("ids: %v; names: %v", ids, names)
  // ids: map[b:hello a:1234]; names: map[second:tianou first:thinkerou]
})

文件上传

一次处理单个文件:

curl -X POST http://localhost:8080/upload \
  -F "file=@/Users/appleboy/test.zip" \
  -H "Content-Type: multipart/form-data"
// Set a lower memory limit for multipart forms (default is 32 MiB)
// 设置表单大小限制
router.MaxMultipartMemory = 8 << 20  // 8 MiB
router.POST("/upload", func(c *gin.Context) {
    // 从form中取出指定的文件字段
    file, _ := c.FormFile("file")
    log.Println(file.Filename)

    // 将文件保存到指定路径
    c.SaveUploadedFile(file, dst)

    c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
  })

一次处理多个文件:

curl -X POST http://localhost:8080/upload \
  -F "upload[]=@/Users/appleboy/test1.zip" \
  -F "upload[]=@/Users/appleboy/test2.zip" \
  -H "Content-Type: multipart/form-data"
router.MaxMultipartMemory = 8 << 20  // 8 MiB
	router.POST("/upload", func(c *gin.Context) {
		// Multipart form
		form, _ := c.MultipartForm()
		files := form.File["upload[]"]

		for _, file := range files {
			log.Println(file.Filename)

			c.SaveUploadedFile(file, dst)
		}
		c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files)))
	})

Gin的中间件

Gin默认启动的路由(gin.Default())自带集成两个中间件:

  1. Logger 日志处理

  2. Recovery 错误处理

启动一个不带中间件的路由

r := gin.New()

启用某些中间件

r := gin.New()
r.Use(gin.Logger())
r.Use(gin.Recovery())

Logger全局中间件

日志写入文件:

func main() {
  
    // Logging to a file.
    f, _ := os.Create("gin.log")
    gin.DefaultWriter = io.MultiWriter(f)

    // Use the following code if you need to write the logs to file and console at the same time.
    // gin.DefaultWriter = io.MultiWriter(f, os.Stdout)

    router := gin.Default()
    router.GET("/ping", func(c *gin.Context) {
        c.String(200, "pong")
    })

    router.Run(":8080")
}

自定义日志格式:

func main() {
	router := gin.New()

	// LoggerWithFormatter middleware will write the logs to gin.DefaultWriter
	// By default gin.DefaultWriter = os.Stdout
	router.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string {

		// your custom format
		return fmt.Sprintf("%s - [%s] \"%s %s %s %d %s \"%s\" %s\"\n",
				param.ClientIP,
				param.TimeStamp.Format(time.RFC1123),
				param.Method,
				param.Path,
				param.Request.Proto,
				param.StatusCode,
				param.Latency,
				param.Request.UserAgent(),
				param.ErrorMessage,
		)
	}))
	router.Use(gin.Recovery())

	router.GET("/ping", func(c *gin.Context) {
		c.String(200, "pong")
	})

	router.Run(":8080")
}

日志着色:

// 默认情况下,会根据选择的tty对日志进行着色
// 禁用日志着色
gin.DisableConsoleColor()

// 始终启用日志着色
gin.ForceConsoleColor()

Recovery全局中间件

路由分组

v1 := router.Group("/v1")
	{
		v1.POST("/login", loginEndpoint)
		v1.POST("/submit", submitEndpoint)
		v1.POST("/read", readEndpoint)
	}

	// Simple group: v2
	v2 := router.Group("/v2")
	{
		v2.POST("/login", loginEndpoint)
		v2.POST("/submit", submitEndpoint)
		v2.POST("/read", readEndpoint)
	}

认证分组

func main() {
	// Creates a router without any middleware by default
	r := gin.New()

	// Global middleware
	// Logger middleware will write the logs to gin.DefaultWriter even if you set with GIN_MODE=release.
	// By default gin.DefaultWriter = os.Stdout
	r.Use(gin.Logger())

	// Recovery middleware recovers from any panics and writes a 500 if there was one.
	r.Use(gin.Recovery())

	// Per route middleware, you can add as many as you desire.
	r.GET("/benchmark", MyBenchLogger(), benchEndpoint)

	// Authorization group
	// authorized := r.Group("/", AuthRequired())
	// exactly the same as:
	authorized := r.Group("/")
	// per group middleware! in this case we use the custom created
	// AuthRequired() middleware just in the "authorized" group.
	authorized.Use(AuthRequired())
	{
		authorized.POST("/login", loginEndpoint)
		authorized.POST("/submit", submitEndpoint)
		authorized.POST("/read", readEndpoint)

		// nested group
		testing := authorized.Group("testing")
		testing.GET("/analytics", analyticsEndpoint)
	}

	// Listen and serve on 0.0.0.0:8080
	r.Run(":8080")
}

最后更新于