gin入門使用

使用 go mod 下載依賴

首先咱們使用 go moudle來管理依賴, go版本要求在 1.11.1 及以上git

export GO111MODULE=on

export GOPROXY=https://mirrors.aliyun.com/goproxy/
複製代碼

初始化 mod 配置github

go mod init

>在當前目錄下會生成 go.mod 文件, 做爲依賴配置.
複製代碼

build項目後會自動下載依賴json

其中在實際項目中發現 goland 沒法識別項目代碼, 須要 在 goland 的 setting 裏設置啓用 Go Modulesapi

goland Preference -> Go -> Go Modules(vgo)
-> Enable Go Modules(vgo)intergration
複製代碼

開始以第一個項目

package main

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

func main() {
	r := gin.Default()

	// get 方式請求
	r.GET("/get", func(c *gin.Context) {
		c.JSON(200, "get")
	})

	// post 方式請求
	r.POST("/post", func(c *gin.Context) {
		c.JSON(200, "post")
	})

	// 任意類型請求
	r.Any("any", func(c *gin.Context) {
		c.JSON(200, "any")
	})

	// handle 指定方式請求
	r.Handle("POST", "/handle_post", func(c *gin.Context) {
		c.JSON(200, "handle post")
	})
   
        //r.Run(":8888") 監聽 8888 端口
        r.Run()
}
複製代碼

這裏咱們定義了經常使用的 get post方法, 經過 debug 能夠看到 any 方式爲咱們建立了全部的能夠實用的請求的方式, 最後使用了 handle 方式指定方法參數. gin.Default 配置默認的參數, Run 啓動 http 服務, 默認監聽 8080 端口bash

curl -XPOST http://127.0.0.1:8080/post
output:
    "post"

curl -XPOST http://127.0.0.1:8080/handle_post
output:
   "handle post"
複製代碼

gin 的路由同請求方式下不能重複定義, 不然啓動將會異常退出markdown

獲取請求參數

package main

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

func main() {
	r := gin.Default()

	// get 方式請求
	r.GET("/getUser/:uid", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"uid": c.Param("uid"),
		})
	})

	r.Run()
}
複製代碼

output:app

curl http://127.0.0.1:8080/getUser/1451
output:
   {"uid":"1451"}
複製代碼

http.StatusOK 引用的 net/http 包中的狀態碼定義, c.Param() 獲取 uid 的值curl

前綴匹配

在工做中咱們但願路由匹配到某個前綴oop

r.GET("/user/*a", func(c *gin.Context) {
	c.String(http.StatusOK, "hello user")
})
複製代碼

這樣只要請求到 user 就能夠攔截到了, 注意在 gin 裏是不容許再設置相似 /user/admin 這樣的路由了. 這裏是沒有路由優先級的.post

請求參數默認值

r.GET("/user", func(c *gin.Context) {
    c.JSON(http.StatusOK, gin.H{
    	"name": c.Query("name"),
    	"sex":  c.DefaultQuery("sex", "女"),
    })
})
複製代碼

請求示例

curl http://127.0.0.1:8080/user?name=1
output:
    {"name":"1","sex":"女"}
複製代碼

獲取post方式請求的參數

c.String(http.StatusOK, c.PostForm("name"))
//獲取name值, 默認值爲小明
c.String(http.StatusOK, c.DefaultPostForm("name", "小明")
複製代碼

請求的json獲取

r.POST("/user", func(c *gin.Context) {
	bodyBytes, error := ioutil.ReadAll(c.Request.Body)
	if error != nil {
		c.String(http.StatusOK, error.Error())
		c.Abort()
	}

	c.String(http.StatusOK, string(bodyBytes))
})
複製代碼
curl -XPOST http://127.0.0.1:8080/user?name=1 -d {"name":1}
output:
  {name:1}
複製代碼

可是經過 readAll 讀取後再獲取值是獲取不到的. 解決方案就是再將值寫回去.

如何將獲取到的json綁定到結構體上

package main

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

type requestUser struct {
	Name string `form:"name"`
	Uid  int    `form:"uid"`
	Age  int    `form:"age"`
	Date time.Time `form:"date"`
}

func main() {
	r := gin.Default()
	r.POST("/user", userAction)
	r.Run()
}

func userAction(c *gin.Context) {
	var requestUser requestUser
    
        //這裏是根據請求的content-type進行解析(能夠解析json)
	if err := c.ShouldBind(&requestUser); err != nil {
		c.String(http.StatusOK, err.Error())
		c.Abort()
	}

	c.String(http.StatusOK, "%v", requestUser)
}

複製代碼
curl -XPOST http://127.0.0.1:8080/user -d 'name=xiaoming&age=23'
output:
    {xiaoming 0 23}

curl -XPOST http://127.0.0.1:8080/user -d 'name=xiaoming&date=2019-01-01'
output:
    parsing time "2019-01-01" as "2006-01-02T15:04:05Z07:00": cannot parse "" as "T"{xiaoming 0 0 0001-01-01 00:00:00 +0000 UTC}
複製代碼

注意咱們在傳遞時間格式的時候解析發生錯誤.

這裏咱們須要定義時間格式結構體解決

type requestUser struct {
	Name string `form:"name"`
	Uid  int    `form:"uid"`
	Age  int    `form:"age"`
	Date time.Time `form:"date" time_format:"2006-01-02"`
}
複製代碼

驗證

type requestUser struct {
	Name string `form:"name" binding:"required,len=10"`
	Uid  int    `form:"uid"`
	Age  int    `form:"age" binding:"required,gt=10"`
}
複製代碼
curl -H "Content-Type:application/json" -XPOST http://127.0.0.1:8080/user -d '{"name":"xiaoming234342342342342","age":11}'
output:
    Key: 'requestUser.Name' Error:Field validation for 'Name' failed on the 'len' tag{xiaoming234342342342342 0 11}
複製代碼

更多驗證規則: godoc.org/gopkg.in/go…

###自定義 validator

type requestUser struct {
	Name string `form:"name" binding:"required,len=10"`
	Uid  int    `form:"uid" binding:"checkUidAvailable"`
	Age  int    `form:"age" binding:"required,gt=10"`
}
複製代碼

編寫 checkUidAvailable

// Structure
func checkUidAvailable(field validator.FieldLevel) bool {
	if fieldValue, ok := field.Field().Interface().(int); ok {
		//隨機機率
		if rand.Intn(2) == fieldValue {
			return true
		}
	}

	return false
}
複製代碼

在 main方法中綁定

func main() {
	r := gin.Default()

	r.POST("/user", userAction)

        //綁定
	if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
		v.RegisterValidation("checkUidAvailable", checkUidAvailable)
	}

	r.Run()
}
複製代碼

方法執行, ShouldBind 自動驗證

func userAction(c *gin.Context) {
	var requestUser requestUser

	if err := c.ShouldBind(&requestUser); err != nil {
		c.String(http.StatusInternalServerError, err.Error())
		c.Abort()
		return
	}
	
	c.String(http.StatusOK, "%v", requestUser)
}
複製代碼

中間件

f, _ := os.Create("gin.log")
gin.DefaultWriter = io.MultiWriter(f)
gin.DefaultErrorWriter = io.MultiWriter(f)

r := gin.New()
r.Use(gin.Logger(), gin.Recovery())
複製代碼

上面咱們使用了 gin.New 實例的方式聲明, r.Use使用了兩個中間件, 一個爲日誌, 另外一個爲碰見 panic 拋出異常最上層, 讓程序正常運行.

f, _ := os.Create("gin.log")
gin.DefaultWriter = io.MultiWriter(f)
gin.DefaultErrorWriter = io.MultiWriter(f)

r := gin.Default()
複製代碼

默認日誌是輸出到控制檯, 將日誌和錯誤日誌所有輸出到 gin.log

自定義中間件

func ipAuthMiddleWare() gin.HandlerFunc {
    return func(c *gin.Context) {
    	ipList := []string{
    		"127.0.0.1",
    	}
    
    	flag := false
    	clientIp := c.ClientIP()
    	for _, host := range ipList {
    		if clientIp != host {
    			flag = true
    			break
    		}
    	}
    
    	if !flag {
    		c.String(http.StatusOK, "error")
    		c.Abort()
    	}
    }
}

---

r.Use(gin.Logger(), gin.Recovery(), ipAuthMiddleWare())
複製代碼

路由組

api := r.Group("/api")
{
	api.GET("user", userAction)
}
複製代碼

訪問 127.0.0.1:8080/api/user 路由組中引入中間件

api := r.Group("/api").Use(ipAuthMiddleWare())
{
	api.GET("user", userAction)
}
複製代碼

一樣使用 use 便可

附錄

json處理: colobu.com/2017/06/21/…

相關文章
相關標籤/搜索