Gin框架路由

作者: TZX_0710 | 来源:发表于2021-08-13 17:34 被阅读0次

    介绍

    • Gin是一个golang的微框架,封装比较优雅,API友好,源码注释比较明确,具有快速灵活,容错方便等特点
    • 对于golang而言,web框架的依赖要远比Python,Java之类的要小。自身的net/http足够简单,性能也非常不错
    • 借助框架开发,不仅可以省去很多常用的封装带来的时间,也有助于团队的编码风格和形成规范

    安装

    1.安装Gin
    go get -u github.com/gin-gonic/gin
    2.引入包
    import "github.com/gin-gonic/gin"
    3.(可选)导入net/http。例如,如果使用常量,则需要这样做http.StatusOK。
    import "net/http"
    
    //示例
    package main
    import ("github.com/gin-gonic/gin")
    func main(){
     //创建路由
     r:=gin.Default()
     r.GET("/",func(c *gin.Context){
         c.String(http.StatusOK,"hello world")
     })
    }
    //监听端口
    //如果不指定端口则默认为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)
     //监听80端口
     r.run(":8000")
    }
    

    API参数

    可以通过Context的Param方法来获取API参数

    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)
    })
    //默认监听8080端口
    c.Run(":8080")
    }
    

    URL参数

    URL参数可以通过DefaultQuery()Query()方法获取

    DefaultQuery()若参数不存在,则返回默认值,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")
    }
    

    表单参数

    表单传输为post请求,http常见的传输格式为四种

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

    表单参数可以通过PostForm()方法获取,该方法默认解析的是x-www-form-urlencoded或form-data格式的参数

    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.创建路由
      // 默认使用了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. 路由拆分成单独的文件或包

    当项目的规模增大后就不太适合继续在项目的main.go文件中去实现注册的相关逻辑,所以更加偏向于抽出路由模块的代码出来,形成单独一个文件

    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)
      }
    }
    
    

    当前目录结构如下

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

    路由拆分成多个文件

    当业务规模继续膨胀,单独的一个routers文件或包已经满足不了需求,所以可以分开定义多个路由文件

    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()
      //加载系统路由
      router.LoadSystem(r)
      //加载用户路由
      router.LoadUser(r)
      if err := r.Run(); err != nil {
          fmt.Println(err)
      }
    }
    

    当前目录结构如下

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

    路由拆分到不同的APP

    项目规模太大,那么更倾向于把业务拆分的更详细一些,例如把不同的业务代码拆分成不同的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项目目录定义

    相关文章

      网友评论

        本文标题:Gin框架路由

        本文链接:https://www.haomeiwen.com/subject/umwdbltx.html