Планировщик задач на Go (Golang): гайд по реализации cron-задач

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Планировщик задач на Go (Golang): от простого ticker до промышленного cron

Планировщик задач (task scheduler) — это компонент, который позволяет выполнять определённые функции в заданное время или с заданной периодичностью. В экосистеме Go (Golang) существует несколько подходов к реализации планировщика: от встроенных примитивов языка до мощных сторонних библиотек. В этой статье мы разберём, как создать планировщик задач на Go, начиная с простых примеров и заканчивая использованием популярной библиотеки robfig/cron.

Зачем нужен планировщик задач в Go?

Go идеально подходит для создания высокопроизводительных серверных приложений, микросервисов и утилит командной строки. Планировщик задач позволяет автоматизировать рутинные операции:

  • Очистка кэша или временных файлов
  • Отправка периодических уведомлений (email, SMS)
  • Сбор метрик и мониторинг
  • Синхронизация данных с внешними API
  • Генерация отчётов по расписанию

Базовый планировщик с использованием time.Ticker

Самый простой способ выполнять задачу каждые N секунд — использовать time.Ticker. Этот встроенный инструмент Go отправляет значение в канал через заданные интервалы времени.

package main

import (
    "fmt"
    "time"
)

func main() {
    ticker := time.NewTicker(2 * time.Second)
    done := make(chan bool)

    go func() {
        for {
            select {
            case <-ticker.C:
                fmt.Println("Задача выполнена:", time.Now().Format(time.RFC3339))
            case <-done:
                ticker.Stop()
                return
            }
        }
    }()

    // Остановим планировщик через 10 секунд
    time.Sleep(10 * time.Second)
    done <- true
    fmt.Println("Планировщик остановлен")
}

Этот код создаёт горутину, которая каждые 2 секунды выводит текущее время. Обратите внимание на использование select — это ключевой паттерн Go для неблокирующей обработки нескольких каналов.

Планировщик с гибким расписанием: библиотека robfig/cron

Для реальных проектов, где требуется cron-подобное расписание (например, «каждый понедельник в 9:00» или «каждые 5 минут с 9 до 18»), лучше всего подходит библиотека github.com/robfig/cron/v3. Она полностью поддерживает стандартный синтаксис cron и добавляет удобные функции, такие как работа с часовыми поясами и обработка паник.

Установка

go get github.com/robfig/cron/v3

Пример использования

package main

import (
    "fmt"
    "log"
    "time"

    "github.com/robfig/cron/v3"
)

func main() {
    c := cron.New(cron.WithSeconds()) // Включаем поддержку секунд

    // Добавляем задачу: каждые 10 секунд
    _, err := c.AddFunc("*/10 * * * * *", func() {
        fmt.Println("Задача 1: каждые 10 секунд", time.Now().Format(time.RFC3339))
    })
    if err != nil {
        log.Fatal(err)
    }

    // Задача: каждый день в 14:30 по UTC
    _, err = c.AddFunc("0 30 14 * * *", func() {
        fmt.Println("Задача 2: ежедневно в 14:30 UTC")
    })
    if err != nil {
        log.Fatal(err)
    }

    // Задача с именем для последующего управления
    entryID, _ := c.AddFunc("@every 1m", func() {
        fmt.Println("Задача 3: каждую минуту")
    })

    c.Start()

    // Удаляем задачу через 5 минут
    time.Sleep(5 * time.Minute)
    c.Remove(entryID)
    fmt.Println("Задача 3 удалена")

    // Блокируем main
    select {}
}

Библиотека поддерживает несколько форматов расписания:

  • Стандартный cron: "30 * * * *" — каждые 30 минут
  • С секундами: "0 30 * * * *" — в 30 секунд каждой минуты
  • @every: "@every 5m" — каждые 5 минут
  • @daily, @weekly, @monthly — предопределённые интервалы

Продвинутый планировщик с контекстом и отменой

В production-среде важно корректно завершать работу планировщика. Используйте context.Context для graceful shutdown:

package main

import (
    "context"                    

Рекомендаций