DefaultServeMux
1.func ListenAndServe(addr string, handler Handler) error
该方法会执行标准的 socket 连接过程,bind -> listen -> accept,当 accept 时启动新的协程处理客户端 socket,调用 Handler.ServeHTTP() 方法,处理结束后返回响应。传入的 Handler 为 nil,会默认使用 DefaultServeMux 作为 Handler
http.HandleFunc() 就是给 DefaultServeMux 添加一条路由以及对应的处理函数
DefaultServeMux.ServeHTTP() 被调用时,则会查找路由并执行对应的处理函数
DefaultServeMux 的作用简单理解就是:路由注册『类似 middware.Use()』、路由匹配、请求处理。
2.Gin 中的路由注册
r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.String(200, "Hello World")
})
r.Run() // listen and serve on 0.0.0.0:8080
func (engine *Engine) Run(addr ...string) (err error) {
// ...
address := resolveAddress(addr)
debugPrint("Listening and serving HTTP on %s\n", address)
err = http.ListenAndServe(address, engine)
return
}
可以发现 http.ListenAndServe() 方法使用了 engine 作为 Handler,『这里要求传入的是一个实现了 ServeHTTP 的实例』即 engine 取代 DefaultServeMux 了来处理路由注册、路由匹配、请求处理等任务。现在直接看 Engine.ServeHTTP()
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// ...
engine.handleHTTPRequest(c)
// ...
}
engine.handleHTTPRequest(c) 通过路由匹配后得到了对应的 HandlerFunc 列表(表示注册的中间件或者路由处理方法,从这里可以看出所谓的中间件和路由处理方法其实是相同类型的。 然后调用 c.Next()开始处理责任链
func (engine *Engine) handleHTTPRequest(c *Context) {
// ...
// Find root of the tree for the given HTTP method
t := engine.trees
for i, tl := 0, len(t); i < tl; i++ {
// ...
// Find route in tree
value := root.getValue(rPath, c.params, unescape)
if value.params != nil {
c.Params = *value.params
}
if value.handlers != nil {
// 这里就是责任链模式的变体
// 通过路由匹配后得到了对应的 HandlerFunc 列表
c.handlers = value.handlers
c.fullPath = value.fullPath
// 调用链上第一个实例的方法就会依次向下调用
c.Next()
c.writermem.WriteHeaderNow()
return
}
// ...
break
}
// ...
}
func (c *Context) Next() {
c.index++
for c.index < int8(len(c.handlers)) {
c.handlers[c.index](c)
c.index++
}
}
3.简化版(理解简单)
type HandlerFunc func(*Request)
type Request struct {
url string
handlers []HandlerFunc
index int // 新增
}
func (r *Request) Use(handlerFunc HandlerFunc) {
r.handlers = append(r.handlers, handlerFunc)
}
// 新增
func (r *Request) Next() {
r.index++
for r.index < len(r.handlers) {
r.handlers[r.index](r)
r.index++
}
}
// 修改
func (r *Request) Run() {
//移动下标到初始的位置
r.index = -1
r.Next()
}
// 测试
// 输出 1 2 3 11
func main() {
r := &Request{}
r.Use(func(r *Request) {
fmt.Print(1, " ")
r.Next()
fmt.Print(11, " ")
})
r.Use(func(r *Request) {
fmt.Print(2, " ")
})
r.Use(func(r *Request) {
fmt.Print(3, " ")
})
r.Run()
首先在 Request 结构体中新增了 index 属性,用于记录当前执行到了第几个 HandlerFunc 然后新增 Next() 方法支持”手动调用责任链 “中之后的 HandlerFunc.另外需要注意的是,Gin 框架中 handlers 和 index 信息放在了 Context 里面
type Context struct {
// ...
handlers HandlersChain
index int8
engine *Engine
// ...
}
其中,HandlersChain 就是一个 HandlerFunc 切片
type HandlerFunc func(*Context)
type HandlersChain []HandlerFunc
gorm 中的责任链模式
GORM 中增删改查都会涉及到责任链模式的使用,比如 Create()、Delete()、Update()、First() 等等,这里以 First() 为例
func (db *DB) First(dest interface{}, conds ...interface{}) (tx *DB) {
// ...
return tx.callbacks.Query().Execute(tx)
}
tx.callbacks.Query() 返回 processor 对象,然后执行其 Execute() 方法
func (cs *callbacks) Query() *processor {
return cs.processors["query"]
}
func (p *processor) Execute(db *DB) *DB {
// ...
for _, f := range p.fns {
f(db)
}
// ...
}
就是在这个位置调用了与操作类型绑定的处理函数。嗯?操作类型是啥意思?对应的处理函数又有哪些?想解决这几个问题,需要搞清楚 callbacks 的定义、初始化、注册。callbacks 定义如下
type callbacks struct {
processors map[string]*processor
}
type processor struct {
db *DB
// ...
fns []func(*DB)
callbacks []*callback
}
type callback struct {
name string
// ...
handler func(*DB)
processor *processor
}
注册完毕后,值类似这样
/*
// ---- callbacks 结构体属性 ----
// processors
{
"create": processorCreate,
"query": ...,
"update": ...,
"delete": ...,
"row": ...,
"raw": ...,
} */
// ---- processor 结构体属性(processorCreate) ----
// callbacks 中有 3 个 callback
/*
{name: gorm:query, handler: Query}
{name: gorm:preload, handler: Preload}
{name: gorm:after_query, handler: AfterQuery}
*/
// fns 对应 3 个 callback 中的 handler,不过是排过序后的
callbacks 在 callbacks.go/initializeCallbacks() 中进行初始化
func initializeCallbacks(db *DB) *callbacks {
return &callbacks{
processors: map[string]*processor{
"create": {db: db},
"query": {db: db},
"update": {db: db},
"delete": {db: db},
"row": {db: db},
"raw": {db: db},
},
}
}
在 callbacks/callbacks.go/RegisterDefaultCallbacks 中进行注册(为了简洁,所贴代码只保留了 query 类型的回调注册)
func RegisterDefaultCallbacks(db *gorm.DB, config *Config) {
// ...
//db.Callback() 返回*callbacks指针,
queryCallback := db.Callback().Query()
queryCallback.Register("gorm:query", Query)
queryCallback.Register("gorm:preload", Preload)
queryCallback.Register("gorm:after_query", AfterQuery)
if len(config.QueryClauses) == 0 {
config.QueryClauses = queryClauses
}
queryCallback.Clauses = config.QueryClauses
// ...
}
所谓操作类型是指增删改查等操作,比如 create、delete、update、query 等等;每种操作类型绑定多个处理函数,比如 query 绑定了 Query()、Preload()、AfterQuery() 方法,其中 Query() 是核心方法,Preload() 实现预加载,AfterQuery() 类似一种 Hook 机制。
// Callback returns callback manager
func (db *DB) Callback() *callbacks {
return db.callbacks
}
func (cs *callbacks) Query() *processor {
return cs.processors["query"]
}
func (p *processor) Register(name string, fn func(*DB)) error {
return (&callback{processor: p}).Register(name, fn)
}