1.初始化流程:
1.1 包的導(dǎo)入過程
首先我們從整體來審視beego包的初始化過程,然后再來逐步分析每一步的詳細(xì)內(nèi)容。
根據(jù)go包的導(dǎo)入過程,我們先來分析一下beego的初始化。包的導(dǎo)入過程如下圖:

1) 在我們自己項(xiàng)目的main包中首先會(huì)導(dǎo)入:
import "github.com/astaxie/beego",
然后go編譯器開始從beego這個(gè)目錄中的第一個(gè)文件admin.go開始讀取,
(注:之所以說是beego目錄而不是包,請(qǐng)參考
https://tonybai.com/2015/03/09/understanding-import-packages/這篇博文的詳解)
然后發(fā)現(xiàn),admin.go中又分別導(dǎo)入了
"github.com/astaxie/beego/grace"
"github.com/astaxie/beego/logs"
"github.com/astaxie/beego/toolbox"
"github.com/astaxie/beego/utils"
四個(gè)目錄,于是編譯器繼續(xù)從上往下依次讀取引入的目錄。
首先,我們進(jìn)入引入的第一個(gè)目錄,grace目錄中。
? 在grace目錄中,我們發(fā)現(xiàn)有四個(gè)文件,分別是:
conn.go,? grace.go, listener.go,server.go。進(jìn)入這四個(gè)文件中發(fā)現(xiàn),它們引入的都是go內(nèi)置的包。(注:由于打算只分析beego框架的內(nèi)容,所以不打算繼續(xù)跟蹤go內(nèi)置包的引入。后期分析go源碼的時(shí)候再繼續(xù)追蹤。)
?? 進(jìn)入到grace目錄中,根據(jù)包的導(dǎo)入過程規(guī)則,編譯器首先會(huì)依次初始化該目錄下所有文件的const常量,然后是該目錄下所有文件的var變量,最后是所有文件的init()函數(shù)。由于grace目錄下只有g(shù)race.go文件中有var變量和init()函數(shù),而其他三個(gè)文件沒有const常量和var變量,也沒有init()函數(shù),所以在編譯運(yùn)行我們自己的App時(shí),首先會(huì)從grace目錄下的grace.go中初始化變量和執(zhí)行g(shù)race.init()函數(shù)。接著,按照上述規(guī)則依次加載logs目錄,toolbox目錄,utils目錄。(注:如果在引入時(shí),把logs和toolbox位置互換,你會(huì)發(fā)現(xiàn),依次加載的目錄是toolbox=>logs=>utils。由此可知,go引入目錄是按照從上到下依次加載的)。
1.2 grace目錄下的初始化,主要在grace.go
1.2.1 聲明一些信號(hào)常量:
const (
// PreSignal is the position to add filter before signal
PreSignal = iota
?? // PostSignal is the position to add filter after signal
PostSignal
?? // StateInit represent the application inited
StateInit
?? // StateRunning represent the application is running
StateRunning
?? // StateShuttingDown represent the application is shutting down
StateShuttingDown
?? // StateTerminate represent the application is killed
StateTerminate
)
1.2.2?聲明Server相關(guān)的變量和http請(qǐng)求需要的一些參數(shù)
var (
?? regLock????????????? *sync.Mutex
?? runningServers??????
map[string]*Server
?? runningServersOrder? []
string
socketPtrOffsetMap?? map[string]uint
runningServersForked bool
// DefaultReadTimeOut is the HTTP read timeout
DefaultReadTimeOut time.Duration
// DefaultWriteTimeOut is the HTTP Write timeout
DefaultWriteTimeOut time.Duration
// DefaultMaxHeaderBytes is the Max HTTP Herder size, default is 0, no limit
DefaultMaxHeaderBytes int
// DefaultTimeout is the shutdown server's timeout. default is 60s
DefaultTimeout = 60 * time.Second
?? isChild???? bool
socketOrder string
hookableSignals []os.Signal
)
1.2.3 初始化1.2.2中的變量
func init() {
?? flag.
BoolVar(&isChild, "graceful", false, "listen on open fd (after forking)")
?? flag.
StringVar(&socketOrder, "socketorder", "", "previous initialization order - used when more than one listener was started")
?? regLock = &sync.Mutex{}
?? runningServers =
make(map[string]*Server)
?? runningServersOrder = []
string{}
?? socketPtrOffsetMap =
make(map[string]uint)
?? hookableSignals = []os.Signal{
????? syscall.
SIGHUP,
syscall.SIGINT,
syscall.SIGTERM,
}
}
1.3??[endif]logs目錄下的初始化
1) ?調(diào)用conn.go中的init(),注冊網(wǎng)絡(luò)日志logger。
2) ? 調(diào)用console.go中的init(),注冊打印到terminal窗口的logger
3 ) ?調(diào)用file.go中的init(),注冊將日志傳輸?shù)轿募械膌ogger
4 ) ?調(diào)用jianliao.go中的init(),注冊jianliao日志(不知道jianliao是什么鬼東西)
5 ?) 調(diào)用multile.go中的init(),注冊multifilelog 日志打印器
6 ) ?調(diào)用slack.go中的init(),注冊SLACKWriter日志打印器
7 ) ?調(diào)用smtp.go中的init(),注冊SMTPWriter日志打印器
1.4??[endif]toolbox目錄下的初始化
1)調(diào)用healthcheck.go中的init(),初始化健康檢查器(HealthChecker)的容器AdminCheckList
func init() {
?? AdminCheckList =
make(map[string]HealthChecker)
}
2)調(diào)用profile.go中的init(),獲取當(dāng)前進(jìn)程的pid,并將值復(fù)制給toolbox包內(nèi)變量pid
func init() {
?? pid = os.
? ? ?Getpid()
}
3)調(diào)用statistics.go中的init(),初始化Statistics,主要是用來統(tǒng)計(jì)請(qǐng)求的url和method的時(shí)間
4) 調(diào)用Tasker.go中的init(),初始化Tasker
1.5 ?config目錄下的初始化,config目錄是由beego目錄下config.go引入的
1)調(diào)用ini.go中的init(),注冊ini格式的IniConfig
2)調(diào)用json.go中的init(),注冊json格式的JsonConfig
1.6 ?context目錄下的初始化
由于context目錄下文件中沒有init()方法,所以在此不做分析了
1.7??[endif]session目錄下的初始化
1)調(diào)用sess_cookie.go中的init(),注冊CookieProvider
2)調(diào)用sess_file.go中的init(),注冊FileProvider
3 )調(diào)用sess_mem.go中的init(),注冊MemProvider
4) 調(diào)用sess_utils.go中的init(),注冊存儲(chǔ)session值可以序列化的數(shù)據(jù)類型
1.8??[endif]beego目錄下的初始化
1)調(diào)用admin.go中的init(),注冊一些beego默認(rèn)路由:qps,prof,healthcheck,listconf等
2)調(diào)用app.go中的init(),初始化一個(gè)Beego的App,BeeApp。
func init() {
// create beego application
BeeApp = NewApp()
}
在NewApp函數(shù)中主要是:1,生成了一個(gè)ControllerRegister結(jié)構(gòu)體(注意這里主要是使用為了ControllerRegister中實(shí)現(xiàn)的ServeHttp方法),2,然后生成一個(gè)App結(jié)構(gòu)體,并將1中生成的ControllerRegister和go內(nèi)置的默認(rèn)的http.Server作為參數(shù)賦給App。
// NewApp returns a new beego application.
func NewApp() *App {
?? cr :=
NewControllerRegister()
?? app := &App{Handlers: cr
, Server: &http.Server{}}
return app
}
3 )調(diào)用config.go的init(),初始化配置文件的默認(rèn)值,以及讀取項(xiàng)目中conf目錄中的app.conf配置文件,并將其值賦值給配置結(jié)構(gòu)體beegoAppConfig
4 )調(diào)用parser.go中的init()
5 ) 調(diào)用template.go中的init(),
1.9 ? 項(xiàng)目根目錄/routers目錄下的初始化
1) 調(diào)用router.go中的init(),該處主要是注冊路由和過濾器
1.10 項(xiàng)目根目錄下的初始化
1) 調(diào)用main.go中的init(),
至此項(xiàng)目所有的初始化流程就走完了。