1. 程式人生 > 實用技巧 >golang 第三方定時任務庫 github.com/robfig/cron/v3 核心原始碼解讀

golang 第三方定時任務庫 github.com/robfig/cron/v3 核心原始碼解讀

定時任務是一個通用場景的功能,在golang中,現在github最為常見的一個第三方定時任務庫就是 github.com/robfig/cron/v3 目前(2020年1月9日) 7.2k Star。
我之前使用Python的時候用慣了apscheduler,切換這個是真的不習慣。

感覺github.com/robfig/cron/v3功能太簡陋了,

  • 不支援定時任務持久化,我重啟一下服務,排程任務資訊就沒了,需要自己儲存排程資訊。
  • 再比如不支援一次定時見issue等,雖然有PR 但是 v3 分支還是依舊不支援,parse檔案函式不支援,雖然可以按照作者的說發,呼叫一次之後再呼叫移除可以實現。
  • 不支援立即執行,
    見issue
    ,作者表示可以呼叫後手動呼叫解決,但是我感覺不夠優雅,沒有指定首次執行時間方便。(我突然有種想提PR的衝動,哈哈哈)

綜上,個人感覺這個庫封裝的不是很完善,作為一個golang新手,讀解析一下這個定時任務庫,還是很有收穫的。如果能力允許,以解決以上問題為目標,自己提PR。

注意

文章內容皆為個人見解,並且只看了核心的實現方式,細節部分沒有解析,不保證準確,如果和你的理解有歧義,以你的為準。

前置知識

你需要掌握golang的 goroutine知識,包括channel通訊,select多路複用等知識,否則解讀起來就會很困難。

簡單的demo

更多使用demo可以參考 個人Go學習筆記


package _1_demo

import (
	"fmt"
	"github.com/robfig/cron/v3"
	"testing"
	"time"
)

// 定時任務
func jobTask() {
	fmt.Printf( "任務啟動: %s \n",time.Now().Format("2006-01-02 15:04:05"))
}

func TestCron(t *testing.T) {
	// 建立一個cron物件
	c := cron.New()

	// 任務排程
	enterId, err := c.AddFunc("@every 3s", jobTask)
	if err!=nil{
		panic(err)
	}
	fmt.Printf("任務id是 %d \n", enterId)
	
	// 啟動定時任務
	c.Start()
	
	// 用於阻塞 後面可以使用 select {} 阻塞
	time.Sleep(time.Second * 9)
}

原始碼解讀

核心檔案主要就是cron.go檔案

首先可以看到 c := cron.New() 建立了這個 Cron結構體物件

type Cron struct {
	entries   []*Entry   // 用於存放job指標物件的陣列
	chain     Chain
	stop      chan struct{}
	add       chan *Entry     
	remove    chan EntryID
	snapshot  chan chan []Entry
	running   bool      // 保證
	logger    Logger
	runningMu sync.Mutex
	location  *time.Location
	parser    ScheduleParser
	nextID    EntryID
	jobWaiter sync.WaitGroup
}

排程任務enterId, err := c.AddFunc("@every 3s", jobTask) 會使用以下兩個檔案來解析定時執行的引數,也就是翻譯給golang 解析@erery 3s是幹什麼