Clone源码
git clone git@github.com:gin-gonic/gin.git
run gin
阅读之前,首先要尝试使用一下。
但是Gin作为依赖库,并没有main方法入口,所以无法直接运行。
我选择创建main package,写一个简单demo以运行Gin框架。
从官方文档,可以看到如下示例:
func main() {
r := gin.Default() //创建上下文
r.GET("/ping", func(c *gin.Context) { //添加路由
c.JSON(http.StatusOK, gin.H{
"message": "pong",
})
})
r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}
在在源码根目录下创建main文件夹,创建main.go,添加以上代码。
# 进入main目录
cd main
# 启动demo
go run .
# 访问ping接口
curl http://127.0.0.1:8080/ping
控制台可以成功地输出pong
gin.Default()
在gin.go文件,可以找到Default方法的源码
// Default returns an Engine instance with the Logger and Recovery middleware already attached.
func Default() *Engine {
debugPrintWARNINGDefault()
engine := New()
engine.Use(Logger(), Recovery())
return engine
}
使用了New()方法创建了一个 Engine 类型实例。
不妨先看看 Engine 类型的定义:
type Engine struct {
RouterGroup
...
}
我觉得一些配置参数可以先忽略,可以看到结构体Engine继承自RouterGroup类型,这很重要,因为demo中下一步添加路由就使用了。
type RouterGroup struct {
Handlers HandlersChain
basePath string
engine *Engine
root bool
}
RouterGroup 类型的定义中一个有趣的点是,包含了一个 Engine 类型成员。此时再来看 New() 方法,
func New() *Engine {
debugPrintWARNINGNew()
engine := &Engine{
RouterGroup: RouterGroup{
Handlers: nil,
basePath: "/",
root: true,
},
...
}
engine.RouterGroup.engine = engine //把自身引用赋值给父类RouterGroup的成员engine
engine.pool.New = func() any {
return engine.allocateContext()
}
return engine
}
可以发现,在实例化 Engine 的过程中,把自身引用赋值给了父类RouterGroup的成员engine。
engine.Get()
在demo的添加路由过程中,调用了实例engine的Get()方法,查看源码
rountergroup.go
func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {
return group.handle(http.MethodGet, relativePath, handlers)
}
func (group *RouterGroup) handle(httpMethod, relativePath string, handlers HandlersChain) IRoutes {
absolutePath := group.calculateAbsolutePath(relativePath)
handlers = group.combineHandlers(handlers)
group.engine.addRoute(httpMethod, absolutePath, handlers)
return group.returnObj()
}
发现Get定义在RouterGroup类型中,是可以直接通过子类型调用父类型的方法的。