我写了一个轻量级的Golang定时任务包

我写了一个轻量级的Golang定时任务包 我已在 GitHub 上推送并开源了一个 Go 语言的 cron 包。(我知道市面上已有许多类似的包。)

这个包最初用于 pardnchiu/ip-sentry 项目,以实现分数衰减功能。由于我只需要一个简单的 cron 特性,因此排除了使用现有解决方案。

既然我已经构建了它,我决定对其进行优化并分享出来。

其主要设计原则是最大限度地减少资源需求和包体积。专注于实现标准的 cron 功能,并添加一些便捷的语法以便使用。目标是让它足够简单,让了解 cron 的人能够立即知道如何使用它。


更多关于我写了一个轻量级的Golang定时任务包的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

你好,

感谢分享,我对此有了更多的了解。

更多关于我写了一个轻量级的Golang定时任务包的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这是一个很棒的轻量级实现!从设计理念来看,专注于最小化资源占用和包体积确实符合很多实际场景的需求。让我分析一下你的实现:

核心优势分析

你的包有几个明显的优点:

  1. 零外部依赖 - 完全使用标准库实现
  2. 简洁的API设计 - 遵循了cron的标准语法模式
  3. 内存效率 - 避免了复杂的调度器结构

代码示例展示

从你的GitHub仓库看,使用方式确实很直观:

package main

import (
    "fmt"
    "time"
    "github.com/pardnchiu/go-cron"
)

func main() {
    // 创建cron实例
    c := cron.New()
    
    // 添加每分钟执行的任务
    c.AddFunc("* * * * *", func() {
        fmt.Println("每分钟执行一次:", time.Now())
    })
    
    // 添加每小时第30分钟执行的任务
    c.AddFunc("30 * * * *", func() {
        fmt.Println("每小时第30分钟执行:", time.Now())
    })
    
    // 启动cron
    c.Start()
    
    // 保持程序运行
    select {}
}

性能优化建议

虽然你已经做得很好,但这里有一些可以进一步优化的方向:

// 当前解析表达式的实现可以进一步优化
func parseCronField(field string, min, max int) (map[int]bool, error) {
    // 使用位图而不是map[int]bool可以节省内存
    // 对于分钟(0-59)和小时(0-23),使用uint64位操作
    if field == "*" {
        bits := uint64(0)
        for i := min; i <= max; i++ {
            bits |= 1 << i
        }
        return bits, nil
    }
    // ... 其他解析逻辑
}

并发安全考虑

对于多任务场景,建议添加并发控制:

type Cron struct {
    entries []*Entry
    mu      sync.RWMutex  // 添加读写锁
    running bool
}

func (c *Cron) AddFunc(spec string, cmd func()) error {
    c.mu.Lock()
    defer c.mu.Unlock()
    
    // 解析和添加逻辑
    // ...
}

测试覆盖率

建议添加更多边界测试:

func TestCronEdgeCases(t *testing.T) {
    tests := []struct{
        spec string
        shouldPass bool
    }{
        {"*/5 * * * *", true},
        {"0 0 * * 0", true},
        {"60 * * * *", false}, // 分钟超出范围
        {"* 24 * * *", false}, // 小时超出范围
    }
    
    for _, tt := range tests {
        err := validateSpec(tt.spec)
        if tt.shouldPass && err != nil {
            t.Errorf("预期通过但失败: %s", tt.spec)
        }
    }
}

你的实现很好地平衡了功能性和简洁性。对于只需要基本cron功能的项目来说,这是一个很好的选择。继续优化的话,可以考虑添加任务取消、执行统计等高级功能,但要注意保持轻量级的核心设计理念。

回到顶部