Padrões Avançados de Projeto em Go com Exemplos de Código

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

Padrões Avançados de Projeto em Go: da Teoria à Prática



Go (Golang) é uma linguagem que incentiva a simplicidade e legibilidade do código. No entanto, quando o projeto cresce, até o código mais conciso pode se transformar em caos sem uma arquitetura adequada. Em nível avançado, desenvolvedores Go utilizam ativamente padrões de projeto, adaptados às características da linguagem: goroutines, channels, interfaces e generics (desde Go 1.18+).



Neste artigo, analisaremos 4 padrões poderosos que ajudarão você a escrever código escalável, testável e de alto desempenho em Go. Cada padrão é acompanhado por um exemplo prático.



1. Padrão Pipeline para processamento de dados em fluxo



Pipeline é um dos padrões mais populares em Go para trabalhar com processamento sequencial de dados. Ele se encaixa perfeitamente no modelo de goroutines e channels. Cada etapa de processamento é executada em uma goroutine separada, e os dados são transmitidos através de channels.



Quando aplicar: Processamento de logs, transformação de dados, processos ETL, streaming de vídeo.



Exemplo: Pipeline para filtragem e transformação de números.



package main

import "fmt"

// Stage 1: Geração de númerosfunc generate(nums ...int) <-chan int { out := make(chan int) go func() { for _, n := range nums { out <- n } close(out) }() return out}

// Stage 2: Multiplicação por 2func multiply(in <-chan int) <-chan int { out := make(chan int) go func() { for n := range in { out <- n * 2 } close(out) }() return out}

// Stage 3: Filtragem (apenas pares)func filterEven(in <-chan int) <-chan int { out := make(chan int) go func() { for n := range in { if n%2 == 0 { out <- n } } close(out) }() return out}

func main() { // Montando o pipeline pipeline := filterEven(multiply(generate(1, 2, 3, 4, 5)))

for result := range pipeline { fmt.Println(result) // Saída: 4, 8 (apenas pares após multiplicação) }}


Vantagens: Processamento paralelo natural, baixo consumo de memória (dados não se acumulam), facilidade para adicionar novas etapas.



2. Fan-Out / Fan-In: escalando o processamento



Este padrão é uma evolução avançada do Pipeline. Fan-Out (ramificação) inicia várias goroutines para processar dados em paralelo a partir de um único channel. Fan-In (fusão) coleta os resultados de vários channels em um único.



Quando aplicar: Parsing de páginas web, processamento de grande quantidade de arquivos, requisições paralelas a APIs.



Exemplo: Verificação paralela de disponibilidade de URLs.



package main

import ( "fmt" "net/http" "sync")

func worker(urls <-chan string, results chan<- string, wg *sync.WaitGroup) { defer wg.Done() for url := range urls { resp, err := http.Get(url) if err != nil { results <- fmt.Sprintf("Erro: %s - %v", url, err) continue } resp.Body.Close() results <- fmt.Sprintf("OK: %s - %d", url, resp.StatusCode) }}

func fanOutFanIn(urls []string, numWorkers int) []string { urlChan := make(chan string, len(urls)) resultChan := make(chan string, len(urls)) var wg sync.WaitGroup

// Fan-Out: iniciando workers for i := 0; i < numWorkers; i++ { wg.Add(1) go worker(urlChan, resultChan, &wg) }

// Enviando URLs for _, url := range urls { urlChan <- url } close(urlChan)

// Aguardando conclusão de todos os workers wg.Wait() close(resultChan)

// Fan-In: coletando resultados var results []string for res := range resultChan { results = append(results, res) } return results}

Blogs

Book Recommendations