- 学习echo源码
- 学习echo.go(servehttp+start+add)
- 学习router.go(insert+find)
- 学习group.go(struct+group+add)
- 学习middleware(middleware chain and custom middleware)
概述
echo框架最巧妙的地方在于echo内部结构体的设计,核心的地方在于路由是如何通过lcp(最长前缀匹配)插入到字典树中,又是如何通过lcp找到对应的路由并且通过链式结构保重中间件按照顺序运行的设计思路,比如:
- group的处理方式,group的结构体中保存有echo实例,但是echo结构体中不含有group,聪明的同学从这里就可以猜出来,这种结构体的设计说明他的所有路由都是插入到echo实例中的,和group没有任何关系,group唯一做的事情就是提供了组级的中间件和prefix,而且从对于echo来说最多只有1级goup子组,在创建2级子组时他会把上一级的group前缀和中间件都取出来,在重新重goup.echo.group中创建一个1级子组
- 他的echo结构体中用router保存该实例下的所有路由,但是router结构体中有保存有这个echo的实例,形成了一个死循环可以一直套娃套下去(这种无限套娃的设计看起来似乎不是很优雅,但是好像也没有更好的办法了)
中间件
echo的中间件逻辑很有趣,他采用了一种链式的结构来保证各种级别的中间件(根组级,组级,路由级)的执行顺序,下面我将以group组下的路由注册为例,来解释中间件的如何保证顺序的,示例代码如下:
package main
import (
"net/http"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
func main() {
//声明echo实例
e := echo.New()
//注册根组中间件
e.Use(middleware.Recover())
//创建一个子组/admin
g := e.Group("/admin")
//在使用子组中间件之前注册一个路由
g.GET("/", hello)
//组级中间件
g.Use(middleware.Logger())
//在使用子组中间件之后注册一个路由
g.GET("/log", log)
//启动echo
e.Logger.Fatal(e.Start(":1323"))
}
func hello(c echo.Context