Gin框架路由 | 青训营笔记

57 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第16天


Gin路由

普通路由

r.GET("/index",func(c *gin.Context){  })
r.POST
...

r.ANY("/index",func(c *gin.Context){
    switch c.Request.Method{
        case "GET":     //GET和POST用了两种写法
            c.JSON(http.StatusOK,gin.H{"message":"get"})
        case http.MethodPost:
            c.JSON(http.StatusOK,gin.H{"message":"post"})
    }
})    //可匹配任意请求方式

//没有配置处理函数的路由,默认返回404:

r.NoRoute(func(c *gin.Context){

    c.JSON(http.StatusNotFound, gin.H{"ERROR!": "NO PAGE!"})

    //c.HTML(http.StatusNotFound,"404.html",nil)

})

路由组

将拥有共同URL前缀的路由划分为一个路由组。习惯性一对{}包裹同组的路由(只是方便看)

func main() {
        r := gin.Default()
        userGroup := r.Group("/user")
        {//访问127.0.0.1/user/index
            userGroup.GET("/index", func(c *gin.Context) {...})
            userGroup.GET("/login", func(c *gin.Context) {...})
            userGroup.POST("/login", func(c *gin.Context) {...})//一般有POST必先有GET
        }
        shopGroup := r.Group("/shop")
        {
            shopGroup.GET("/index", func(c *gin.Context) {...})
            shopGroup.GET("/cart", func(c *gin.Context) {...})
            shopGroup.POST("/checkout", func(c *gin.Context) {...})
        }
        r.Run()
}

路由组嵌套:

shopGroup := r.Group("/shop")
        {
            shopGroup.GET("/index", func(c *gin.Context) {...})
            // 嵌套路由组
            xx := shopGroup.Group("xx")
            xx.GET("/oo", func(c *gin.Context) {...})
        }

路由原理

Gin框架中的路由使用的是httprouter这个库。

其基本原理就是构造一个路由地址的前缀树。

路由拆分成单独的文件(包)

都在package main

*gin-demo
*--main.go
*--routers.go(有setRouter函数)

func setRouter() *gin.Engine{
    r:=gin.Default()
    r.GET("/index",indexHandler) //indexHandler中间件在此文件,略
    return r
}

//直接用,没区别
func main(){
    r:=setRouter()    //r是*gin.Engine类型
    if err:=r.Run();err!=nil{
        fmt.Println("start service failed, err:%v\n",err)
    }
}

在不同的package里,如main和router

*gin-demo
*--main.go
*--*router
   *--router.go

注意把函数setRouter首字母改成大写

package main
import "gin-demo/router"
func main(){
    r:=router.SetRouter()
}

也可以让SetRouter函数写成:
func SetRouter(e *gin.Engine){
    e.GET("/index",indexHandler)
}
这样
func main(){
    r:=gin.Default()
    router.SetRouter(r) //这样可以不用把所有的路由注册都写在SetRouter里
    //router.SetUser(r)    //单独注册到指定路由
    //router.SetService(r)
}

路由拆分到不同的APP

将不同APP单独设置一个文件夹
gin_demo
├── app
│   ├── blog
│   │   ├── handler.go
│   │   └── router.go
│   └── shop
│       ├── handler.go
│       └── router.go
├── main.go
└── routers
    └── routers.go
blog和shop的router.go都有同名的Routers函数

routers/routers.go中根据需要定义Include函数用来注册子app中定义的路由,Init函数用来进行路由的初始化操作:
******

type Option func(*gin.Engine)
var options = []Option{}
// 注册app的路由配置
func Include(opts ...Option) {
        options = append(options, opts...)
}

// 初始化
func Init() *gin.Engine {
        r := gin.Default()
        for _, opt := range options {
                opt(r)
        }
        return r
}

******

main.go中按如下方式先注册子app中的路由,然后再进行路由的初始化:
func main() {
        // 加载多个APP的路由配置
        routers.Include(shop.Routers, blog.Routers)
        // 初始化路由
        r := routers.Init()
        if err := r.Run(); err != nil {
                fmt.Println("startup service failed, err:%v\n", err)
        }
}