Golang 的多任務調度系統:從 BaseJob 到 ProductJob 的 "泛型" 與 "繼承" 實現

 突破 Go 語言限制! 揭祕如何用組合 + 接口實現類繼承效果,打造高擴展任務調度系統。以 BaseJob 泛型基類和 ProductJob 實戰爲例,深度解析:

  1. 基礎架構:BaseJob 的 "泛型" 實現

在 lib/basejob.go 中,我們定義了一個基礎任務結構體,它使用類型參數實現了類似泛型的功能:

type BaseJob[T model.JobConfig] struct {
    JobConfig   T
    JobName     string
    Description string
    RetryCount  int
    EasyFunc    interface{}
}

這裏的關鍵點是:

func (job *BaseJob[T]) DoError(err error, description string) {
    job.RetryCount++
    log.Println(description, err)
    // 更新任務狀態
}
func (job *BaseJob[T]) GetSyncConfig() error {
    // 獲取任務配置的通用實現
}
  1. "繼承" 模式:ProductJob 的實現

在 jobs/productjob/easyjob.go 中,我們通過組合實現了類似繼承的模式:

type EasyJob[T model.ByIdConfig] struct {
    easylib.BaseJob[model.ByIdConfig]
}

這裏的關鍵設計:

  1. 嵌入 BaseJob:ProductJob 通過嵌入 BaseJob 獲得所有基礎功能
  2. 方法重寫:ProductJob 重寫了關鍵方法來實現具體業務邏輯

方法重寫示例

數據獲取方法重寫

func (job *EasyJob[T]) GetDataPageList() ([]interface{}, []interface{}, interface{}, error) {
    jobConfig := job.JobConfig
    maxPid := easylib.GetMaxPid()
    if jobConfig.Lastid >= maxPid {
        return nil, nil, maxPid, nil
    }
    // 調用具體業務查詢
    products, delProducts, lastId, err := QueryProduct(jobConfig.Lastid, jobConfig.Limit)
    data := easylib.MapperFromProducts(products)
    deleteData := easylib.MapperFromProducts(delProducts)
    return data, deleteData, lastId, nil
}

ES 更新方法重寫

func (job *EasyJob[T]) UpdateEs(data []interface{}) error {
    ps := easylib.MapperToProducts(data)
    err := products.BulkInsert(ps)
    return err
}
  1. 多態實現:接口與運行時綁定

在 BaseJob 的 Run 方法中,我們通過類型斷言實現了運行時多態:

func (job *BaseJob[T]) Run() {
    // ...
    data, delData, last, err := job.EasyFunc.(EasyFunc).GetDataPageList()
    // ...
    err := job.EasyFunc.(EasyFunc).UpdateEs(data)
    // ...
}

這裏的關鍵:

  1. 任務管理器設計

任務管理器 (lib/jobmanager.go) 統一管理所有任務:

type EasyJobParam struct {
    JobName     string
    Status      int
    Description string
    RetryCount  int
    Interval    time.Duration
}
var EasyJobManager = struct {
    Jobs map[string]*EasyJobParam
    Lock sync.RWMutex
}{
    Jobs: make(map[string]*EasyJobParam),
}

總結

通過這種設計,我們實現了:

  1. 配置泛型化:通過類型參數支持不同任務的配置
  2. 代碼複用:BaseJob 提供通用實現,減少重複代碼
  3. 靈活擴展:新任務只需嵌入 BaseJob 並重寫關鍵方法
  4. 統一管理:任務管理器集中控制所有任務狀態

雖然 Golang 沒有傳統面向對象的繼承機制,但通過組合 + 接口 + 方法重寫,我們實現了同樣強大的抽象能力。這種模式在需要高擴展性的系統中特別有用,如我們的任務調度系統。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/L-u_Ad9NZFO131NmV54jQQ