Планировщик задач на Go (Golang): cron, gocron и asynq

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

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

Начать курс

Планировщик задач на Go (Golang): от cron до asynq

В современной серверной разработке на Go (Golang) часто возникает необходимость выполнять код по расписанию или с задержкой. Очистка кэша, рассылка уведомлений, генерация отчётов — все это требует надёжного планировщика задач. В этой статье мы подробно разберём три популярных подхода: стандартный пакет cron, легковесную библиотеку gocron и распределённую очередь asynq. Вы узнаете, какой инструмент выбрать для вашего проекта на PythonLib.

1. Стандартный cron для Go

Библиотека github.com/robfig/cron/v3 — это де-факто стандарт для планирования повторяющихся задач в Go. Она использует знакомый синтаксис cron-выражений (5 полей) и поддерживает секунды, часовые пояса и recovery от паник.

Установка и базовый пример

go get github.com/robfig/cron/v3

Пример планировщика, который запускает задачу каждые 30 секунд:

package main

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

func main() {
    c := cron.New()
    
    // Добавляем задачу с cron-выражением: каждые 30 секунд
    _, err := c.AddFunc("*/30 * * * * *", func() {
        fmt.Println("Задача выполнена:", time.Now())
    })
    if err != nil {
        panic(err)
    }
    
    c.Start()
    
    // Блокируем main горутину
    select {}
}

Ключевые особенности:

  • Поддержка стандартных cron-выражений (5 или 6 полей с секундами)
  • Автоматическое восстановление после паники в задаче
  • Возможность задать часовой пояс через cron.WithLocation()
  • Логирование через cron.WithLogger()

Продвинутое использование: цепные джобы

c := cron.New(cron.WithSeconds())

// Задача с именем для управления
id, _ := c.AddFunc("@every 5m", func() {
    fmt.Println("Выполняется каждые 5 минут")
})

// Удаление задачи по ID
c.Remove(id)

// Остановка планировщика
c.Stop()

Библиотека идеально подходит для простых периодических задач внутри одного процесса. Однако для распределённых систем (несколько реплик Go-сервера) потребуется внешняя блокировка, чтобы задача не выполнялась одновременно на всех нодах.

2. Gocron — лёгкий шедулер с цепочками

github.com/go-co-op/gocron предлагает более современный API без cron-выражений. Вместо строк вы используете цепочки методов. Это особенно удобно для новичков.

Пример с gocron

package main

import (
    "fmt"
    "time"
    "github.com/go-co-op/gocron"
)

func main() {
    s := gocron.NewScheduler(time.UTC)
    
    // Задача выполняется каждые 2 минуты
    _, _ = s.Every(2).Minutes().Do(func() {
        fmt.Println("Прошло 2 минуты")
    })
    
    // Задача с задержкой после старта
    _, _ = s.Every(1).Day().At("10:30").Do(func() {
        fmt.Println("Ежедневно в 10:30")
    })
    
    s.StartBlocking()
}

Преимущества gocron:

  • Человекочитаемый API: .Every(10).Seconds()
  • Встроенная поддержка распределённых блокировок через Redis (опционально)
  • Возможность задать лимит на количество запусков
  • Глобальные и локальные обработчики ошибок

Если вам нужно простое решение для микросервиса без внешних зависимостей — gocron станет отличным выбором. Он легче cron'а и не требует знания синтаксиса cron-выражений.

3. Asynq — распределённая очередь отложенных задач

github.com/hibiken/asynq — это не просто планировщик, а полноценная система очередей на базе Redis. Она позволяет откладывать задачи, задавать приоритеты, повторять сбойные задачи и отслеживать их статус через веб-интерфейс.

Архитектура asynq

Asynq состоит из двух частей: клиента (отправляет задачи) и воркера (выполняет). Оба используют Redis как брокер сообщений.

// Клиент — отправка задачи
client := asynq.NewClient(asynq.RedisClientOpt{Addr: "localhost:637                    

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