Por que a Arquitetura orientada a eventos em Go é a nova faixa preta no desenvolvimento?
\n\nImagine uma orquestra onde cada músico toca sua parte, sem esperar pelo maestro, mas ainda assim cria uma sinfonia perfeita. É exatamente assim que funciona a arquitetura orientada a eventos em Go — cada serviço vive sua própria vida, reage a eventos e produz novos, sem bloquear o fluxo geral.
\n\nEm um mundo onde os usuários exigem respostas instantâneas e os sistemas processam milhões de requisições por segundo, as APIs REST síncronas começam a "engasgar". Go, com suas goroutines leves e suporte nativo a concorrência, torna-se a linguagem ideal para construir sistemas reativos. Mas como transformar o caos das chamadas assíncronas em uma arquitetura organizada? Vamos descobrir.
\n\nO que é Arquitetura orientada a eventos (EDA) e por que Go?
\n\nArquitetura orientada a eventos em Go é um paradigma onde os componentes do sistema se comunicam através de eventos, em vez de chamadas diretas. Em vez de o serviço A esperar pela resposta do serviço B, ele simplesmente publica uma mensagem em um broker, e B a captura quando estiver pronto.
\n\nPor que Go é ideal para EDA?
\n- \n
- Goroutines — "threads" baratas para processamento paralelo de eventos (é possível executar um milhão sem problemas) \n
- Canais — mecanismo embutido para transmitir eventos entre goroutines \n
- Compilação rápida — iterações em microsserviços tornam-se extremamente rápidas \n
- Simplicidade — menos "mágica", mais controle \n
Construindo o primeiro sistema orientado a eventos em Go: do simples ao complexo
\n\nNível 1: Eventos internos através de canais
\nVamos começar pelo básico. Imagine que estamos escrevendo um sistema de monitoramento de servidor. Cada evento (queda de memória, aumento de CPU) deve ser processado assincronamente.
\n\npackage main\n\nimport (\n "fmt"\n "math/rand"\n "time"\n)\n\ntype Event struct {\n Type string\n Payload interface{}\n}\n\nfunc main() {\n // Criando um canal para eventos\n eventChannel := make(chan Event, 100)\n \n // Produtor: gerando eventos\n go func() {\n for {\n time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)\n event := Event{\n Type: "system.memory.alert",\n Payload: map[string]interface{}{\n "usage_pct": rand.Float64() * 100,\n "timestamp": time.Now(),\n },\n }\n eventChannel <- event\n }\n }()\n \n // Consumidor: processando eventos\n go func() {\n for event := range eventChannel {\n fmt.Printf("Evento recebido: %s\\n", event.Type)\n processEvent(event)\n }\n }()\n \n time.Sleep(5 * time.Second)\n}\n\nfunc processEvent(e Event) {\n // Simulação de processamento\n time.Sleep(200 * time.Millisecond)\n fmt.Printf("Processado: %v\\n", e.Payload)\n}\n\nIsso é o básico, mas para produção é necessário algo mais. Quando o número de serviços ultrapassa uma dezena, os brokers de mensagens entram em cena.
\n\nNível 2: Arquitetura orientada a eventos em Go com NATS
\nNATS é um broker leve que se integra perfeitamente com Go. É mais rápido que RabbitMQ e mais simples que Kafka.
\n\npackage main\n\nimport (\n "log"\n "time"\n "github.com/nats-io/nats.go"\n)\n\ntype OrderEvent struct {\n OrderID string `json:"order_id"`\n Status string `json:"status"`\n Amount float64 `json:"amount"`\n Time time.Time `json:"time"`\n}\n\nfunc main() {\n // Conectando ao NATS\n nc, err := nats.Connect(nats.DefaultURL)\n if err != nil {\n log.Fatal(err)\n }\n defer nc.Close()\n \n // Publicando evento (produtor)\n event := OrderEvent{\n OrderID: "ORD-12345",\n Status: "created",\n Amount: 299.99,\n Time: time.Now(),\n }\n \n data, _ := json.Marshal(event)\n