Feature flags em Go: como gerenciar lançamentos sem medo e dor

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

Feature flags em Go: quando cada linha de código é um risco

\n\n

Você já acordou às 3 da manhã porque um novo lançamento "matou" a produção? Ou passou horas revertendo mudanças porque uma nova funcionalidade quebrou a lógica da antiga? Familiar? Então feature flags (flags de funcionalidades) é o que vai mudar radicalmente sua vida como desenvolvedor Go.

\n\n

Feature flags não são apenas "if-else" no código. É uma filosofia de lançamentos seguros. É a capacidade de ativar e desativar funcionalidades sem deploy, realizar testes A/B e fazer canary releases. No mundo Go, onde velocidade e confiabilidade são as principais prioridades, feature flags se tornam uma ferramenta must-have.

\n\n

O que são feature flags e por que são necessárias em Go?

\n\n

Feature flag (também conhecido como toggle, flag de funcionalidade) é um mecanismo que permite ativar ou desativar uma funcionalidade específica do aplicativo sem alterar o código e sem um novo deploy. Em palavras simples: você escreve o código, envolve-o em uma condição, e se a flag estiver ativa — o código é executado, se não — é ignorado.

\n\n

Em Go, onde a compilação em binário estático e a arquitetura minimalista são o padrão, feature flags resolvem vários problemas de uma vez:

\n\n
    \n
  • Redução do risco de lançamentos — lançou uma funcionalidade, mas algo deu errado? Basta desativar a flag. Sem reversão, sem novo deploy.
  • \n
  • Teste A/B — mostramos a nova versão para apenas 10% dos usuários, comparamos métricas.
  • \n
  • Canary releases — ativação gradual da funcionalidade para diferentes grupos de usuários.
  • \n
  • Dark launches — o código já está em produção, mas oculto. Permite testar integrações sem impacto nos usuários.
  • \n
  • Gerenciamento de dependências — ativamos a funcionalidade somente quando a infraestrutura backend estiver pronta.
  • \n
\n\n

Como implementar feature flags em Go: do simples ao complexo

\n\n

1. A maneira mais simples: constantes e variáveis de ambiente

\n\n

Vamos começar pelo básico. A opção mais primitiva, mas funcional, é usar constantes globais ou variáveis de ambiente. Adequado para MVP ou quando não é necessária dinamicidade.

\n\n
package main\n\nimport (\n    "fmt"\n    "os"\n)\n\nconst NewCheckoutFlowEnabled = false\n\nfunc main() {\n    envFlag := os.Getenv("FEATURE_NEW_PAYMENT")\n    isPaymentEnabled := envFlag == "true"\n\n    if isPaymentEnabled {\n        fmt.Println("Novo gateway de pagamento ativo")\n        processNewPayment()\n    } else {\n        fmt.Println("Usando gateway de pagamento antigo")\n        processOldPayment()\n    }\n}\n\nfunc processNewPayment() {\n    fmt.Println("Processando via Stripe API v3")\n}\n\nfunc processOldPayment() {\n    fmt.Println("Processando via Stripe API v2")\n}
\n\n

As desvantagens são óbvias: não há gerenciamento dinâmico, é necessário reiniciar o aplicativo. Mas para cenários simples, serve.

\n\n

2. Abordagem estrutural: seu próprio gerenciador de flags

\n\n

Quando o número de flags ultrapassa 5, é hora de extrair a lógica para um pacote separado. Vamos criar um gerenciador simples de feature flags com suporte a armazenamento in-memory.

\n\n
package feature\n\nimport (\n    "sync"\n    "time"\n)\n\ntype Flag struct {\n    Name      string\n    Enabled   bool\n    UpdatedAt time.Time\n}\n\ntype Manager struct {\n    mu    sync.RWMutex\n    flags map[string]Flag\n}\n\nfunc NewManager() *Manager {\n    return &Manager{\n        flags: make(map[string]Flag),\n    }\n}\n\nfunc (m *Manager) IsEnabled(name string) bool {\n    m.mu.RLock()\n    defer m.mu.RUnlock()\n    flag, exists := m.flags[name]\n    return exists && flag.Enabled\n}\n\nfunc (m *Manager) Enable(name string) {\n    m.mu.Lock()\n    defer m.mu.Unlock()\n    m.flags[name] = Flag{\n        Name:      name,\n        Enabled:   true,\n        UpdatedAt: time.Now(),\n    }\n}\n\nfunc (m *Manager) Disable(name string) {\n    m.mu.Lock()\n    defer m.mu.Unlock()\n    m.flags[name] = Flag{\n        Name:      name,\n        Enabled:   false,\n        UpdatedAt:                

Blogs

Book Recommendations