这一篇主要说明application.go的主要构成和其中用到方法的主要作用。
参数定义
application.go中定义了初始化时需要用到的常量和变量
常量定义:
const (
INDEX_CACHE = "index" //各类别下rank
ALL_RANK_CACHE = "all_rank" //总的rank
BANGUMI_CACHE = "bangumi" //番剧
BANGUMI_LIST_CACHE = "bangumi_list" //新番放松表
SORT_TOP_CACHE = "sort-" //具体某个类别rank(这个在index_cache中要用到)
LIVE_INDEX_CACHE = "live_index" //直播rank
)
全局变量定义:
var (
ProdLevels = []log.Level{
log.InfoLevel,
log.NoticeLevel,
log.WarnLevel,
log.ErrorLevel,
log.PanicLevel,
log.AlertLevel,
log.FatalLevel,
}
)
这里主要定义了release模式下用到的日志级别。(PS:类库引用的是"github.com/go-playground/log")
结构体定义
type BiliBiliApplication struct {
Router *gin.Engine //路由
Corn *CornService //初始化服务
Conf *Config //配置信息
Client *client.BCli //客户端
Cache *CacheManager //缓存管理
}
这里定义了Bilibili-go主体程序的结构。
初始化rank数据并注册任务
application.go中使用了conformTask方法进行了数据的初始化以及任务注册
//application.go
conformTask(app)
corn.Start()
conformTask方法如下:
//application.go
func conformTask(app *BiliBiliApplication) {
app.Corn.RegisterTask(&IndexInfoTask{CornTask: CornTask{Name: "index_info", Duration: 2 * time.Hour}, app: app})
app.Corn.RegisterTask(&BangumiInfoTask{CornTask: CornTask{Name: "bangumi_info", Duration: 6 * time.Hour}, app: app})
app.Corn.RegisterTask(&BangumiListTask{CornTask: CornTask{Name: "bangumi_list", Duration: 6 * time.Hour}, app: app})
app.Corn.RegisterTask(&TopRankTask{CornTask: CornTask{Name: "top_rank", Duration: 2 * time.Hour}, app: app})
app.Corn.RegisterTask(&LiveIndexTask{CornTask: CornTask{Name: "alive_index", Duration: 2 * time.Hour}, app: app})
}
从方法名上看是调用了CornService中的RegisterTask(注册任务)的方法,那么,我们看一下这个RegisterTask方法到底做了些什么吧。
//corn.go
//execute task
func exec(f CornTaskImpl) {
log.Info("invoke task, taskname: ", f.GetName())
defer func() {
if r := recover(); r != nil {
log.Error(r)
}
}()
if err := f.Run(); err != nil {
f.Failure(err)
} else {
f.Success()
}
log.Info("run task end, taskname: ", f.GetName())
}
//这里就是那个名为注册任务的方法
func (c *CornService) RegisterTask(task CornTaskImpl) {
task.SyncLastRunTime()
exec(task)
c.tasks = append(c.tasks, task)
}
不难发现,实际上这个注册任务的方法就是将task执行了一下,然后放到c.tasks数组里。
而之后的corn.Start()方法:
//corn.go
func (c *CornService) syncTaskList(nowTime time.Time) {
for _, task := range c.tasks { //循环任务列表
//Unix timestamp => duration
between := time.Duration(nowTime.Unix()-task.GetLastRun().Unix()) * time.Second
if between >= task.GetDuration() { //当时间间隔大于设定的时间周期则执行,并修改LastRun的值
task.SyncLastRunTime()
exec(task)
}
}
}
func (c *CornService) loop() {
for {
select {
case <-c.done:
log.Info("corn loop stopped....")
return
case nowTime := <-c.ticker.C: //这里通过计时器获取到当前时间
go c.syncTaskList(nowTime)
}
}
}
func (c *CornService) Start() {
go c.loop()
}
corn.Start()方法开启了一个loop线程,这个线程简单的来说就是每隔一分钟执行一次syncTaskList方法。
到此,bilibili-go这个小项目的学习也基本上告一段落了,剩下的内容基本上都是数据获取和处理的部分。这个项目虽然很小,但是对多线程的学习,go的基础都有很大的帮助,在此也感谢WhiteBlue大大,(^_^)