Beego源码解析(四)-Hook函数

时间:2021-06-14 17:15:36

原文链接:
Beego源码解析(四)-Hook函数

在前三篇文章中,介绍了 Beego作为 Web框架最基本的配置解析路由机制请求处理三个流程.现在我们应该就已经对 Beego很是了解
后面的文章就让我们重新头开始看看除了这三个基本功能外,Beego还做了什么其他的事情吧~

这篇文章会介绍在 Beego启动时调用的6个 hook函数

关于 Beego源码的注释可以看我的Github
回到最开始的 beego.Run()函数(beego.go:53)。可以看到在函数的第一行就有一个

initBeforeHTTPRun()

而且这个函数定义也就在下面紧挨着

func initBeforeHTTPRun() {
    //讲每个函数添加到 hooks中,并且逐个调用
    AddAPPStartHook(registerMime)
    AddAPPStartHook(registerDefaultErrorHandler)
    AddAPPStartHook(registerSession)
    AddAPPStartHook(registerDocs)
    AddAPPStartHook(registerTemplate)
    AddAPPStartHook(registerAdmin)

    for _, hk := range hooks {
        if err := hk(); err != nil {
            panic(err)
        }
    }
}

这里看到有个 hooks变量,它在本文件的37行被定义

type hookfunc func() error

var (
    hooks = make([]hookfunc,0)
)

func AddAppStartHook(hf hookfunc){
        hooks = append(hooks,hf)
}

这样就很清楚了,hooks是一个保存函数的切片,而在 initBeforeHTTPRun()中通过调用 AddAppStartHook函数将对应的函数添加进 hooks中
在函数的最后也可以看到是通过一个 range调用保存在 hooks里的所有函数
那么这添加进去的6个函数又是干么的呢?

在 hooks.go中可以看到他们的身影

registerMime

这个函数比较短,它只是使用了标准库的 mime包,向其中添加关联,这个 mimemaps不出所料也是一个 map[string][string]类型的map,其中包含了所有对应的关联信息.想要了解的可以查看 mime.go这个文件

func registerMine() error{
        for k,v:=range mimemaps{
                mime.AddExtensionType(k,v)
        }
        return nil
}

registerDefaultErrorHandler

这个函数也同样很好理解,它定义了不同出错码对应的函数,然后用 ErrorHandler函数注册进一个叫 ErrorMaps的 map[string]*errInfo类型的map中,并在以后用于出错处理
关于出错处理的这几个函数可以参考 error.go文件,并不是很复杂就不多说了

func registerDefaultErrorHandler() error {
    m := map[string]func(http.ResponseWriter, *http.Request){
        "401": unauthorized,
        "402": paymentRequired,
        "403": forbidden,
        "404": notFound,
        "405": methodNotAllowed,
        "500": internalServerError,
        "501": notImplemented,
        "502": badGateway,
        "503": serviceUnavailable,
        "504": gatewayTimeout,
    }
    for e, h := range m {
        if _, ok := ErrorMaps[e]; !ok {
            ErrorHandler(e, h)
        }
    }
    return nil
}

registerSession

这个函数看名字就知道是关于 Session的,它会通过配置文件判断是否开启了 Session,并且获得配置
再然后就通过调用 Session包里的 NewManger函数获得一个 Session管理器的实例,并且使用 goroutine开始一个Gc()来管理 Session
这里的 GlobalSessions在 config.go:114行被声明,作用于全局
关于 Seesion管理器可能(额=.=)以后会更新说明

func registerSession() error {
    // BConfig(位于 config.go内的全局变量)
    if BConfig.WebConfig.Session.SessionOn {
        var err error
        sessionConfig := AppConfig.String("sessionConfig")
        if sessionConfig == "" {
            // 启用默认的 Session配置
            conf := map[string]interface{}{
                "cookieName":      BConfig.WebConfig.Session.SessionName,
                "gclifetime":      BConfig.WebConfig.Session.SessionGCMaxLifetime,
                "providerConfig":  filepath.ToSlash(BConfig.WebConfig.Session.SessionProviderConfig),
                "secure":          BConfig.Listen.EnableHTTPS,
                "enableSetCookie": BConfig.WebConfig.Session.SessionAutoSetCookie,
                "domain":          BConfig.WebConfig.Session.SessionDomain,
                "cookieLifeTime":  BConfig.WebConfig.Session.SessionCookieLifeTime,
            }
            confBytes, err := json.Marshal(conf)
            if err != nil {
                return err
            }
            sessionConfig = string(confBytes)
        }
        if GlobalSessions, err = session.NewManager(BConfig.WebConfig.Session.SessionProvider, sessionConfig); err != nil {
            return err
        }
        //开启一个goroutine来处理session的回收,定义于 session.session.go:227
        go GlobalSessions.GC()
    }
    return nil
}

registerTemplate

构建模板的函数,这样在以后使用模板可以更加方便
关于模板的函数可以看 template.go文件
以后可能(额=.=)会有关于模板的介绍…

func registerTemplate() error {
    if err := BuildTemplate(BConfig.WebConfig.ViewsPath); err != nil {
        if BConfig.RunMode == DEV {
            Warn(err)
        }
        return err
    }
    return nil
}

registerDocs

Beego的自动化文档是否开始,可以看出这里就只是注册了两个路由
关于自动化文档的使用可以看官方文档

func registerDocs() error {
    if BConfig.WebConfig.EnableDocs {
        Get("/docs", serverDocs)
        Get("/docs/*", serverDocs)
    }
    return nil
}

registerAdmin

在 Beego的文档中都知道有一个叫进程内监控的功能,如果配置文件开启了,那么这里就会用 goroutine开启一个监控
相关的使用方法可以参考官方文档
也可以参考 beego/admin.go文件

func registerAdmin() error {
    if BConfig.Listen.EnableAdmin {
        go beeAdminApp.Run()
    }
    return nil
}

这篇文章比较短,因为这几个函数的逻辑都比较简单。分别处理哪些事情看名字都比较容易知道
想要更深入了解的可以查看相关的源文件

如果错误,希望指正:D