«¿Y dónde están mis parámetros opcionales?» — el grito del alma de un desarrollador Go
Acabas de migrar a Go desde Python o JavaScript y estás escribiendo una función para enviar un correo electrónico. En Python se vería así:
def send_email(to, subject, cc=None, bcc=None, attachments=None): passTodo simple: cc, bcc y attachments son parámetros opcionales. Puedes no pasarlos y la función funcionará con valores por defecto.
Pero aquí está el problema: en Go no hay sobrecarga de métodos ni argumentos nombrados con valores por defecto. La comunidad de Stack Overflow lo confirma: la pregunta «Optional Parameters in Go?» acumula miles de visitas. Es un dolor real para los principiantes.
La buena noticia: en Go hay al menos 5 formas elegantes de resolver este problema. En este artículo las analizaremos todas, desde las simples hasta las industriales.
¿Por qué Go es tan «estricto»?
El equipo de Go deliberadamente renunció a los parámetros opcionales para:
- Simplificar la lectura del código — siempre ves cuántos argumentos se pasan a una función.
- Evitar comportamientos mágicos — sin valores predeterminados inesperados.
- Acelerar la compilación — menos azúcar sintáctico.
Pero esto no significa que no puedas hacer el código flexible. Veamos cómo sortear las limitaciones.
Forma 1: Funciones variádicas (Variadic Functions) — «barato y efectivo»
La forma más simple es usar los tres puntos ... para pasar un número variable de argumentos del mismo tipo.
package main
import "fmt"
// Sum acepta cualquier cantidad de números enterosfunc 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 — también funciona}Ventajas: simplicidad, soporte integrado del lenguaje.
Desventajas: todos los argumentos deben ser del mismo tipo. No se puede decir «pasa un string y luego un int opcional».
Las funciones variádicas en Go son ideales para loggers, sumadores y cualquier operación donde la cantidad de datos sea desconocida de antemano.
Forma 2: Estructura de configuración (Configuration Struct) — «cuando hay muchos parámetros»
Si tienes más de 2-3 parámetros opcionales de diferentes tipos, usa una estructura.
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("Modo HTML activado") } if len(cfg.CC) > 0 { fmt.Printf("CC: %v", cfg.CC) }}
func main() { // Usamos valores por defecto (zero values) SendEmail("user@example.com", "Hello", "Body", EmailConfig{})
// Sobrescribimos algunos campos cfg := EmailConfig{ CC: []string{"boss@example.com"}, IsHTML: true, } SendEmail("user@example.com", "Hello", "Body", cfg)}Observa: los zero values en Go (cadena vacía, 0, nil para slices) se convierten en valores por defecto. Esta es nuestra implementación de parámetros opcionales en Go mediante estructuras.
Ventajas: legible, tipado, fácil de extender.
Desventajas: hay que crear una estructura cada vez, incluso si no cambias nada.
Forma 3: Patrón Functional Options — «el estándar de oro de Go»
Este patrón fue creado por Dave Cheney, uno de los desarrolladores clave de Go. Se utiliza en bibliotecas como gRPC, AWS SDK y la propia biblioteca estándar de Go (por ejemplo,
Blogs
Book Recommendations
Leer también
Microservicios en Java: arquitectura y práctica para el desarrollador
API GraphQL en C++: tutorial paso a paso con ejemplos prácticos
Trabajo con JSON en Swift: análisis y serialización para principiantes
Currículum para Python Junior: Guía y ejemplos efectivos
Documentación del proyecto Go: mejores prácticas y ejemplos de código