Gin框架系列02:路由與參數

回顧

上一節咱們用Gin框架快速搭建了一個GET請求的接口,今天來學習路由和參數的獲取。前端

請求動詞

熟悉RESTful的同窗應該知道,RESTful是網絡應用程序的一種設計風格和開發方式,每個URI表明一種資源,客戶端經過POSTDELETEPUTGET四種請求方式來對資源作增刪改查的操做。git

一樣的,Gin框架給咱們提供的除這4種動詞外,還有PATCHOPTIONHEAD等,詳細內容能夠查看rentergroup.go文件的IRoutes接口。github

type IRoutes interface {
    Use(...HandlerFunc) IRoutes

    Handle(string, string, ...HandlerFunc) IRoutes
    Any(string, ...HandlerFunc) IRoutes
    GET(string, ...HandlerFunc) IRoutes
    POST(string, ...HandlerFunc) IRoutes
    DELETE(string, ...HandlerFunc) IRoutes
    PATCH(string, ...HandlerFunc) IRoutes
    PUT(string, ...HandlerFunc) IRoutes
    OPTIONS(string, ...HandlerFunc) IRoutes
    HEAD(string, ...HandlerFunc) IRoutes

    StaticFile(string, string) IRoutes
    Static(string, string) IRoutes
    StaticFS(string, http.FileSystem) IRoutes
}複製代碼

由於RenterGroup實現了IRoutes定義的全部請求動詞,並且gin.Default返回的Engine類型繼承了RenterGroup,因此使用起來很是簡單,只須要經過gin.Default實例化對象,接下來全部的路由操做都經過該對象使用便可。golang

file

func main() {
    router := gin.Default()
    router.POST("/article", func(c *gin.Context) {
        c.String(200, "article post")
    })
    router.DELETE("/article", func(c *gin.Context) {
        c.String(200, "article delete")
    })
    router.PUT("/article", func(c *gin.Context) {
        c.String(200, "article put")
    })
    router.GET("/article", func(c *gin.Context) {
        c.String(200, "article get")
    })
    router.Run()
}複製代碼

請求動詞的第一個參數是請求路徑,第二個參數是用於邏輯處理的函數,能夠是匿名的或是其餘地方定義的函數名。不一樣的請求動詞能夠定義相同的路徑,只須要切換動詞就能夠進入對應的處理邏輯。shell

curl -X PUT http://localhost:8080/article
curl -X POST http://localhost:8080/article
curl -X GET http://localhost:8080/article
curl -X DELETE http://localhost:8080/article複製代碼

路由參數

GET請求有兩種,一種是在URL後加上?name=pingye,這種是有參數名的,另外一種是在路徑中直接加上參數值/article/1,這種沒有參數名,須要在代碼中解析參數。數組

protocol://hostname:[port]/path/[query]#fragment複製代碼

咱們先來看路由攜帶參數值的玩法,這裏有一道題,怎麼利用Gin獲取下面連接的參數值1服務器

file

實現方式很是簡單,只須要在路由中設置好佔位符:id,冒號爲佔位符的標誌,冒號後面的參數名能夠自定義,Gin會將路由與請求地址進行匹配,若匹配成功會將1賦值爲佔位符:id,只需調用c.Param就能夠獲取id的值。網絡

router.GET("/article/:id", func(c *gin.Context) {
  id := c.Param("id")
  c.String(200, id)
})複製代碼

可是,:id佔位符會存在一個問題,若是id參數值傳空就會有404的錯誤提示。app

file

因而Gin提供了另外一種佔位符*id,使用它就能夠達到取空值的目的。框架

router.GET("/article/*id", func(c *gin.Context) {
  id := c.Param("id")
  c.String(200, id)
})複製代碼

普通參數

除了路由攜帶參數值外,接下來看比較傳統的GET傳參方式。

http://localhost:8080/welcome?firstname=Jane&lastname=Doe複製代碼

能夠經過c.Queryc.DefaultQuery方法獲取問號後的參數。

router.GET("/welcome", func(c *gin.Context) {
   firstname := c.DefaultQuery("firstname", "pingyeaa")
   lastname := c.Query("lastname")
   c.String(200, firstname+" "+lastname)
})複製代碼

這二者最終都調用了GetQuery方法,惟一的區別是DefaultQuery作了默認值處理。

func (c *Context) DefaultQuery(key, defaultValue string) string {
    if value, ok := c.GetQuery(key); ok {
        return value
    }
    return defaultValue
}

func (c *Context) Query(key string) string {
    value, _ := c.GetQuery(key)
    return value
}複製代碼

表單參數

從HTML提交過來的表單form內容一樣也能夠輕鬆獲取。

router.POST("/form_post", func(c *gin.Context) {
  message := c.PostForm("message")
  nick := c.DefaultPostForm("nick", "anonymous")

  c.JSON(200, gin.H{
    "status":  "posted",
    "message": message,
    "nick":    nick,
  })
})複製代碼
curl -d "message=pingye" http://localhost:8080/form_post
{"message":"pingye","nick":"anonymous","status":"posted"}複製代碼

數組類型參數

有時候(例如複選框)前端頁面會傳來數組類型的值,這種類型name相同,但存儲的內容不一樣。

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

依然是一個QueryMap方法就搞定,該方法默認返回map類型。

router.GET("/post", func(c *gin.Context) {
  ids := c.QueryMap("ids")
  c.String(200, ids["a"]+" "+ids["b"])
})複製代碼
curl http://localhost:8080/post?ids[a]=pingye&ids[b]=hehe
pingye hehe複製代碼

文件上傳

通常狀況下,文件上傳會由前端直接傳給雲存儲服務商,好比阿里雲、七牛雲等,比較少的場景會傳給本身的服務器。爲了不書到用時方恨少的狀況發生,咱們來了解一下。

Gin提供了FormFile方法獲取文件流,這個方法返回了一個FileHeader類型的變量,能夠調用Filename屬性來查看文件名。

type FileHeader struct {
   Filename string
   Header   textproto.MIMEHeader
   Size     int64

   content []byte
   tmpfile string
}複製代碼
router.POST("/upload", func(c *gin.Context) {
  file, _ := c.FormFile("file")
  c.String(200, file.Filename)
})複製代碼

經過curl請求接口,能夠看到輕鬆獲取文件名稱。

curl -X POST http://localhost:8080/upload \
  -F "file=@/Users/enoch/Downloads/IMG_9216.JPG" \
  -H "Content-Type: multipart/form-data"
IMG_9216.JPG複製代碼

固然不止能夠拿到文件名,咱們還可使用SaveUploadedFile方法將文件保存到某個地方,文件保存時要確保有目標目錄的操做權限。

router.POST("/upload", func(c *gin.Context) {
        file, _ := c.FormFile("file")
        c.String(200, file.Filename)
        err := c.SaveUploadedFile(file, "/Users/enoch/Desktop/ab.png")
        if err != nil {
            c.String(500, err.Error())
        }
})複製代碼

路由分組

當接口發生重大變動(好比入參出參)時,考慮到向下兼容,通常會新增一個接口,可是又但願新接口的名稱顯而易見地看出是老接口的升級版,那麼就能夠在接口名前加上版本號v1/article這種形式。

v1 := r.Group("v1")
{
  v1.POST("/login", func(c *gin.Context) {
    c.String(200, "v1/login")
  })
  v1.POST("/submit", func(c *gin.Context) {
    c.String(200, "v1/submit")
  })
}

v2 := r.Group("v2")
{
  v2.POST("/login", func(c *gin.Context) {
    c.String(200, "v2/login")
  })
  v2.POST("/submit", func(c *gin.Context) {
    c.String(200, "v2/submit")
  })
}複製代碼
curl -X POST http://localhost:8080/v1/login
curl -X POST http://localhost:8080/v2/login複製代碼

Go語言庫代碼示例,歡迎star github.com/pingyeaa/go…


感謝你們的觀看,若是以爲文章對你有所幫助,歡迎關注公衆號「平也」,聚焦Go語言與技術原理。 關注我

相關文章
相關標籤/搜索