Filas de Tarefas em Go: Um Guia Prático

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: por que precisamos de filas de tarefas em Go?

\n

No desenvolvimento moderno, frequentemente surge a necessidade de processar tarefas de forma assíncrona, sem bloquear o fluxo principal da aplicação. Filas de tarefas (task queues) são um padrão clássico que permite distribuir o trabalho entre vários processadores (workers), gerenciar a carga e garantir tolerância a falhas.

\n

A linguagem Go (Golang) fornece mecanismos integrados para implementar filas de tarefas: goroutines e canais (channels). Neste artigo, vamos analisar na prática como construir uma fila de tarefas confiável usando a biblioteca padrão do Go, sem recorrer a brokers de mensagens externos (embora em produção RabbitMQ ou Redis possam ser úteis).

\n\n

Parte Principal

\n\n

1. Padrão Básico de Worker Pool

\n

Worker Pool é um conjunto de um número fixo de goroutines (workers) que escutam um único canal e processam as tarefas recebidas. Isso permite controlar o grau de paralelismo e evitar sobrecarga do sistema.

\n

Vamos considerar um exemplo simples: criamos um pool de 3 workers que processam números inteiros (simulação de trabalho).

\n
package main\n\nimport (\n    "fmt"\n    "sync"\n    "time"\n)\n\nfunc worker(id int, jobs <-chan int, wg *sync.WaitGroup) {\n    defer wg.Done()\n    for job := range jobs {\n        fmt.Printf("Worker %d iniciou a tarefa %d\\n", id, job)\n        time.Sleep(time.Second) // simulação de trabalho\n        fmt.Printf("Worker %d concluiu a tarefa %d\\n", id, job)\n    }\n}\n\nfunc main() {\n    const numJobs = 5\n    const numWorkers = 3\n\n    jobs := make(chan int, numJobs)\n    var wg sync.WaitGroup\n\n    // Iniciando os workers\n    for w := 1; w <= numWorkers; w++ {\n        wg.Add(1)\n        go worker(w, jobs, &wg)\n    }\n\n    // Enviando tarefas\n    for j := 1; j <= numJobs; j++ {\n        jobs <- j\n    }\n    close(jobs) // fechando o canal para que os workers terminem\n\n    wg.Wait()\n    fmt.Println("Todas as tarefas concluídas")\n}
\n

Análise do código:

\n
    \n
  • jobs — canal com buffer para onde enviamos as tarefas.
  • \n
  • worker — função que lê do canal e processa cada tarefa.
  • \n
  • sync.WaitGroup — aguarda a conclusão de todos os workers.
  • \n
  • Após enviar todas as tarefas, o canal é fechado (close(jobs)), o que faz com que o loop for range nos workers termine.
  • \n
\n

Este padrão é a base para soluções mais complexas.

\n\n

2. Fila com Prioridades e Timeouts

\n

Em aplicações reais, as tarefas podem ter prioridades diferentes ou exigir execução dentro de um determinado tempo. Vamos implementar uma fila onde tarefas com prioridade são processadas primeiro, e também adicionar um contexto com timeout para cancelar tarefas longas.

\n
package main\n\nimport (\n    "context"\n    "fmt"\n    "time"\n)\n\ntype Task struct {\n    ID       int\n    Priority int // quanto menor o número, maior a prioridade\n    Data     string\n}\n\nfunc processTask(ctx context.Context, task Task) error {\n    select {\n    case <-ctx.Done():\n        return ctx.Err()\n    case <-time.After(time.Duration(task.Priority) * 500 * time.Millisecond):\n        fmt.Printf("Tarefa processada %d: %s (prioridade %d)\\n", task.ID, task.Data, task.Priority)\n        return nil\n    }\n}\n\nfunc main() {\n    tasks := []Task{\n        {ID: 1, Priority: 3, Data: "Baixa prioridade"},\n        {ID: 2, Priority: 1, Data: "Alta prioridade"},\n        {ID: 3, Priority: 2, Data: "Prioridade média"},\n    }\n\n    // Ordenação por prioridade (as mais altas primeiro)\n    // Em um projeto real, use ordenação ou heap (container/heap)\n    for i := 0; i < len(tasks); i++ {\n        for j := i + 1; j < len(tasks); j++ {\n            if tasks[j].Priority < tasks[i].Priority {\n                tasks[i], tasks[j] = tasks[j], tasks[i]\n            }\n                

Blogs

Book Recommendations