Gin框架路由

介紹

  • Gin是一個golang的微框架,封裝比較優(yōu)雅,API友好,源碼注釋比較明確,具有快速靈活,容錯方便等特點
  • 對于golang而言,web框架的依賴要遠比Python,Java之類的要小。自身的net/http足夠簡單,性能也非常不錯
  • 借助框架開發(fā),不僅可以省去很多常用的封裝帶來的時間,也有助于團隊的編碼風(fēng)格和形成規(guī)范

安裝

1.安裝Gin
go get -u github.com/gin-gonic/gin
2.引入包
import "github.com/gin-gonic/gin"
3.(可選)導(dǎo)入net/http。例如,如果使用常量,則需要這樣做http.StatusOK。
import "net/http"

//示例
package main
import ("github.com/gin-gonic/gin")
func main(){
 //創(chuàng)建路由
 r:=gin.Default()
 r.GET("/",func(c *gin.Context){
     c.String(http.StatusOK,"hello world")
 })
}
//監(jiān)聽端口
//如果不指定端口則默認為8080
c.run(":80")

基本路由

gin框架中采用的路由庫是基于httprouter做的

package main
import(
"net/http"
"github.com/gin-gonic/gin"
)
func main(){
 r:=gin.Default()
 r.GET("/",func(c *gin.Context){
     c.String(http.StatusOK,"hello word")
 })
 r.POST("/delUser",DelUser)
 //監(jiān)聽80端口
 r.run(":8000")
}

API參數(shù)

可以通過Context的Param方法來獲取API參數(shù)

package main
import(
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
func main(){
r:=gin.Default()
r.GET("/user/:name/*action",func(c *gin.Context){
  name:=c.Param("name")
  action:=c.Param("acion")
  //截取
  action=strings.Trim(action,"/")
  c.String(http.StatusOK,name+"is"+action)
})
//默認監(jiān)聽8080端口
c.Run(":8080")
}

URL參數(shù)

URL參數(shù)可以通過DefaultQuery()Query()方法獲取

DefaultQuery()若參數(shù)不存在,則返回默認值,Query()若不存在則返回空字符串

package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main(){
 r:=gin.Default()
 r.GET("/user",func(c *gin.Context){
     name:= c.DefaultQuery("name","Nice")
     c.String(http.StatusOK,fmt.Sprintf("%s",name))
 })
 c.Run(":8000")
}

表單參數(shù)

表單傳輸為post請求,http常見的傳輸格式為四種

  • application/json
  • application/x-www-form-urlencoded
  • application/xml
  • multipart/form-data

表單參數(shù)可以通過PostForm()方法獲取,該方法默認解析的是x-www-form-urlencoded或form-data格式的參數(shù)

package main
import(
    "fmt"
  "net/http"
    "github.com/gin-gonic/gin"
)
func main(){
    r:=gin.Default()
    r.POST("form",func(c *gin.Context){
        types:=c.DefaultPostForm("type","post")
        username:=c.PostForm("userName")
        password:=c.PostForm("pwd")
        c.String(http.StatusOk,fmt.Sprintf("%v",username)
    })
        c.Run(":8000")
}

單個文件

  • multipart/form-data格式用于文件上傳

  • gin文件上傳與原生的net/http方法類似,不同于在gin把原生的request封裝到c.Request中

package main
import (
  "github.com/gin-gonic/gin"
)
func main(){
    r:=gin.Default()
    //限制上傳最大尺寸
    r.MaxMultipartMemory=8<<20
    r.POST("/upload",func(c *gin.Context){
        file,err:=c.FormFile("file")
        if err!=nil{
            c.String(500,"上傳出錯")
            c.SaveUploadedFile(file,file.Filename)
            c.String(http.StatusOK,file.Filename)
        }
    })
    c.Run(":800")
}

上傳多個文件

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

func main() {
  // 1.創(chuàng)建路由
  // 默認使用了2個中間件Logger(), Recovery()
  r := gin.Default()
  // 限制表單上傳大小 8MB,默認為32MB
  r.MaxMultipartMemory = 8 << 20
  r.POST("/upload", func(c *gin.Context) {
      form, err := c.MultipartForm()
      if err != nil {
          c.String(http.StatusBadRequest, fmt.Sprintf("get err %s", err.Error()))
      }
      // 獲取所有圖片
      files := form.File["files"]
      // 遍歷所有圖片
      for _, file := range files {
          // 逐個存
          if err := c.SaveUploadedFile(file, file.Filename); err != nil {
              c.String(http.StatusBadRequest, fmt.Sprintf("upload err %s", err.Error()))
              return
          }
      }
      c.String(200, fmt.Sprintf("upload ok %d files", len(files)))
  })
  //默認端口號是8080
  r.Run(":8000")
}

routees group

routes group 是為了管理一些相同的URL

package main
import (
"github.com/gin-gonic/gin"
"net/http"
"fmt"
)
func main(){
    r:=gin.Default()
}

路由的拆分與注冊

  1. 基本的路由注冊 適用于路由條目較少的簡單下面或者項目demo
package main

import (
    "net/http"

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

func helloHandler(c *gin.Context) {
    c.JSON(http.StatusOK, gin.H{
        "message": "Hello www.topgoer.com!",
    })
}

func main() {
    r := gin.Default()
    r.GET("/topgoer", helloHandler)
    if err := r.Run(); err != nil {
        fmt.Println("startup service failed, err:%v\n", err)
    }
}
  1. 路由拆分成單獨的文件或包

當(dāng)項目的規(guī)模增大后就不太適合繼續(xù)在項目的main.go文件中去實現(xiàn)注冊的相關(guān)邏輯,所以更加偏向于抽出路由模塊的代碼出來,形成單獨一個文件

package router

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

func helloHandler(c *gin.Context) {
  c.JSON(http.StatusOK, gin.H{
      "message": "Hello www.topgoer.com",
  })
}

// SetupRouter 配置路由信息
func SetupRouter() *gin.Engine {
  r := gin.Default()
  r.GET("/topgoer", helloHandler)
  return r
}

package main

import (
  "fmt"
  "router_example/router"
)

func main() {
  r := router.SetupRouter()
  if err := r.Run(); err != nil {
      fmt.Println("err failed", err)
  }
}

當(dāng)前目錄結(jié)構(gòu)如下

router_example
├── go.mod
├── main.go
└── router
    └── routers.go

路由拆分成多個文件

當(dāng)業(yè)務(wù)規(guī)模繼續(xù)膨脹,單獨的一個routers文件或包已經(jīng)滿足不了需求,所以可以分開定義多個路由文件

package router

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

func LoadSystem(e *gin.Engine) {
  r := gin.Default()
  {
      r.GET("findSystemId", findSystemId)
        r.GET("findAll",findAll)
  }
}
package router

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

func LoadUser(e *gin.Engine) {
  r := gin.Default()
  {
      r.GET("findByUserId", findByUserId)
      r.GET("findAllUser", findAllUser)
  }
}

main.go
func main() {
  r := gin.Default()
  //加載系統(tǒng)路由
  router.LoadSystem(r)
  //加載用戶路由
  router.LoadUser(r)
  if err := r.Run(); err != nil {
      fmt.Println(err)
  }
}

當(dāng)前目錄結(jié)構(gòu)如下

router_example
├── go.mod
├── main.go
└── router
    └── user.go
    └── system.go

路由拆分到不同的APP

項目規(guī)模太大,那么更傾向于把業(yè)務(wù)拆分的更詳細一些,例如把不同的業(yè)務(wù)代碼拆分成不同的APP

router_example
├──app
|  ├──user
|  |  ├──handle.go
|  |  ├──router.go
|  ├──system
|  |  ├──handle.go
|  |  ├──router.go
├── go.mod
├── main.go
└── router
    └── routers.go
system
package system

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

func findBySystemId(c *gin.Context) {
  c.JSON(http.StatusOK, gin.H{
      "message": "findBySystemId",
  })
}
package system

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

func Routers(e *gin.Engine) {
  e.GET("findBySystemId", findBySystemId)
}
user
package user
import (
  "github.com/gin-gonic/gin"
  "net/http"
)
func findByUserId(c *gin.Context) {
  c.JSON(http.StatusOK, gin.H{
      "message": "findByUserId",
  })
}
package user

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

func Routers(e *gin.Engine) {
  e.GET("findByUserId", findByUserId)
}

package main

import (
  "fmt"
  "router_example/router"
  "router_example/service/system"
  "router_example/service/user"
)

func main() {
  //加載多個路由
  router.Include(user.Routers, system.Routers)
  //初始化
  r := router.Init()
  if err := r.Run(); err != nil {
      fmt.Println(err)
  }
}




Gin項目目錄定義
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容