"E onde estão meus parâmetros opcionais?" — o grito de alma do desenvolvedor Go
Você acabou de migrar para Go vindo do Python ou JavaScript e está escrevendo uma função para enviar e-mail. Em Python, seria assim:
def send_email(to, subject, cc=None, bcc=None, attachments=None): passTudo simples: cc, bcc e attachments são parâmetros opcionais. Você pode não passá-los, e a função funcionará com valores padrão.
Mas eis o problema: em Go não há sobrecarga de métodos nem argumentos nomeados com valores padrão. A comunidade Stack Overflow confirma: a pergunta "Optional Parameters in Go?" acumula milhares de visualizações. É uma dor real para iniciantes.
A boa notícia: em Go existem pelo menos 5 maneiras elegantes de resolver esse problema. Neste artigo, vamos analisar todas elas — das simples às industriais.
Por que o Go é tão "rígido"?
A equipe do Go deliberadamente abriu mão de parâmetros opcionais para:
- Simplificar a leitura do código — você sempre vê quantos argumentos estão sendo passados para a função.
- Evitar comportamento mágico — sem valores padrão inesperados.
- Acelerar a compilação — menos açúcar sintático.
Mas isso não significa que você não possa tornar o código flexível. Vamos ver como contornar as limitações.
Método 1: Funções Variádicas (Variadic Functions) — "barato e eficaz"
A maneira mais simples é usar reticências ... para passar um número variável de argumentos do mesmo tipo.
package main
import "fmt"
// Sum aceita qualquer quantidade de números inteirosfunc Sum(nums ...int) int { total := 0 for _, n := range nums { total += n } return total}
func main() { fmt.Println(Sum(1, 2, 3)) // 6 fmt.Println(Sum(10, 20)) // 30 fmt.Println(Sum()) // 0 — também funciona}Prós: simplicidade, suporte nativo da linguagem.
Contras: todos os argumentos devem ser do mesmo tipo. Não é possível dizer "passe uma string e depois um int opcional".
Funções variádicas em Go são ótimas para loggers, somadores e qualquer operação onde a quantidade de dados é desconhecida de antemão.
Método 2: Estrutura de Configuração (Configuration Struct) — "quando há muitos parâmetros"
Se você tem mais de 2-3 parâmetros opcionais de tipos diferentes — use uma estrutura.
package main
import "fmt"
type EmailConfig struct { CC []string BCC []string Attachments []string IsHTML bool}
func SendEmail(to, subject, body string, cfg EmailConfig) { fmt.Printf("To: %s, Subject: %s", to, subject) if cfg.IsHTML { fmt.Println("HTML mode enabled") } if len(cfg.CC) > 0 { fmt.Printf("CC: %v", cfg.CC) }}
func main() { // Usando valores padrão (zero values) SendEmail("user@example.com", "Hello", "Body", EmailConfig{})
// Sobrescrevendo alguns campos cfg := EmailConfig{ CC: []string{"boss@example.com"}, IsHTML: true, } SendEmail("user@example.com", "Hello", "Body", cfg)}Observe: zero values em Go (string vazia, 0, nil para slices) tornam-se valores padrão. Esta é a nossa implementação de parâmetros opcionais em Go através de estruturas.
Prós: legível, tipado, fácil de estender.
Contras: é necessário criar uma estrutura toda vez, mesmo que nada seja alterado.
Método 3: Functional Options Pattern — "o padrão ouro do Go"
Este padrão foi criado por Dave Cheney, um dos principais desenvolvedores do Go. É usado em bibliotecas como gRPC, AWS SDK e na própria biblioteca padrão do Go (por exemplo,
Blogs
Book Recommendations
Leia também
Entrevista Swift: guia completo de preparação com exemplos de código
Serverless em PHP: AWS Lambda e alternativas para backend sem servidor
Como escrever uma API REST em Swift em 30 minutos
10 melhores frameworks TypeScript para desenvolvimento web avançado
Monorepositório com Java: organização de código para iniciantes