Funciones Variádicas y Tipos de Función
Go trata las funciones como valores que puedes nombrar, pasar y retornar, y permite que el último parámetro absorba una lista de argumentos variable con ...T.
Busca en todas las páginas de la documentación
Go trata las funciones como valores que puedes nombrar, pasar y retornar, y permite que el último parámetro absorba una lista de argumentos variable con ...T.
Juntos, las firmas variádicas y los tipos de función potencian middleware, opciones y pequeños puntos de extensión sin la sobrecarga de interfaces.
Un parámetro variádico (args ...int) es azúcar sintáctico para un slice dentro de la función.
Los llamadores pasan cero o más argumentos, o expanden un slice existente con fn(slice...).
Un tipo de función (type Handler func(...)) documenta contratos invocables y permite funciones de orden superior que aceptan comportamiento como datos.
Usa variádicos para constructores como fmt.Sprintf, ayudantes de registro y opciones funcionales.
Usa tipos de función para middleware HTTP, envoltorios de reintento y predicados.
Prefiere interfaces pequeñas cuando necesites múltiples métodos relacionados o mocking entre paquetes.
Tarjeta de receta de referencia rápida - lista para copiar y pegar.
type Option func(*Server)
func WithPort(p int) Option {
return func(s *Server) { s.port = p }
}
func New(opts ...Option) *Server {
s := &Server{port: 8080}
for _, opt := range opts {
opt(&s)
}
return s
}
type Middleware func(http.Handler) http.Handler
func Logging(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Println(r.Method, r.URL.Path)
next.ServeHTTP(w, r)
})
}Cuándo usar esto:
WithTimeout, WithLogger, ...).Retry, Authorize).sum, concat).package retry
import (
"context"
"errors"
"time"
)
type AttemptFunc func(ctx context.Context) error
func Do(ctx context.Context, attempts int, backoff time.Duration, fn AttemptFunc) error {
var err error
for i := 0; i < attempts; i++ {
if err = fn(ctx); err == nil {
return nil
}
if ctx.Err() != nil {
return ctx.Err()
}
time.Sleep(backoff)
backoff *= 2
}
return err
}
func ExampleUsage(ctx context.Context, call func(context.Context) error) error {
return Do(ctx, 3, 100*time.Millisecond, func(ctx context.Context) error {
if err := call(ctx); err != nil {
return err
}
return nil
})
}
var ErrPermanent = errors.New("retry: permanent failure")Lo que esto demuestra:
AttemptFunc nombra el contrato invocable en lugar de repetir func(context.Context) error.Do de orden superior acepta comportamiento y se encarga de la política de bucle/retraso.ExampleUsage adapta una call más simple a AttemptFunc.... en el sitio de llamada divide un slice en argumentos discretos.func(int) int a type Op func(int) int sin conversión, pero la conversión está permitida cuando las firmas coinciden.nil deben verificarse antes de la llamada; invocar nil provoca un pánico como una llamada a método de interfaz nil.| Regla | Detalle |
|---|---|
| Posición | El parámetro variádico debe ser el último |
| Dentro del cuerpo | El tipo es []T, usa len, range normalmente |
| Cero argumentos | Válido - el slice es no nulo, longitud 0 |
| Expansión | fn(slice...) requiere tipo de slice []T exactamente |
| Mezcla | No se puede pasar un argumento no variádico después de la captura variádica |
| Mecanismo | Fortaleza | Límite |
|---|---|---|
Tipo func | Un método, cero sobrecarga | Sin agrupación nombrada de múltiples métodos |
| Interfaz | Mocking, evolución mediante incrustación | Dobles de prueba más amplios |
| Genéricos + func | Algoritmos reutilizables | Firmas más pesadas |
var fn func()
if fn != nil {
fn()
}Siempre protege los callbacks opcionales.
Las cadenas de middleware deben tratar nil como identidad: if mw == nil { return next }.
if fn != nil antes de invocar, o requiere no nulo en la documentación de la API.args == nil es falso para una llamada de cero argumentos (slice vacío no nulo). Solución: usa len(args) == 0 cuando distinguir ausente vs vacío importe.[]byte no se puede dividir en ...int. Solución: convierte o cambia la firma.New.Op(fn) cuando sea necesario.CallSlice. Solución: cíñete a llamadas tipadas a menos que estés construyendo herramientas genéricas.
| Alternativa | Usar Cuando | No Usar Cuando |
|---|---|---|
| Interfaz pequeña | Múltiples métodos, mocks generados | Hook de estilo ServeHTTP único |
| Opciones de struct | Necesita validación entre campos | Solo una o dos perillas |
Patrón Builder (Chain().Use()) | Registro de middleware fluido | Un slice []Middleware simple es suficiente |
Genéricos func F[T any](...) | Utilidades de map/filter seguras en tipo | Carga de plugins en tiempo de ejecución |
Declara un parámetro variádico de tipo slice []T.
La función recibe todos los argumentos finales como un solo slice.
Usa fn(items...) donde items es []T.
Sin ..., pasas el slice como un único argumento (error de tipo si la firma es variádica).
Sí, a menos que valides len(args) == 0 y devuelvas un error.
fmt.Println() es un ejemplo familiar.
Un tipo nombrado cuyo tipo subyacente es una firma de función.
Permite métodos en funciones (ver http.HandlerFunc) y APIs más claras.
Inyecta funciones AttemptFunc o de reloj para simular fallos sin interfaces.
Las pruebas pasan cierres que registran invocaciones.
func(http.Handler) http.Handler es el estándar del ecosistema para net/http.
gRPC usa tipos de función de interceptor de manera similar.
La cabecera del slice se pasa por valor; los elementos se referencian.
Mutar args[0] dentro de la función afecta a los elementos del llamador si comparten el array subyacente.
Sí, los receptores coexisten con los parámetros variádicos: func (l *Logger) Info(msg string, kv ...any).
Las opciones escalan campos opcionales sin romper a los llamadores.
La configuración requerida grande todavía encaja en una struct validada una vez en New.
No; usa opciones funcionales, structs de configuración o envoltorios de estilo de sobrecarga (Dial() llamando a DialContext(context.Background(), ...)).
Sí; el tipo de valor es la firma de la función o el tipo nombrado.
Recuerda que las claves de mapa no pueden ser slices; las claves deben ser comparables.
Los genéricos reducen la duplicación para algoritmos de slice; los tipos de función aún expresan inyección en tiempo de ejecución y hooks de E/S.
HandlerFunc)Versiones de Stack: Esta página fue escrita para Go 1.26.x (predeterminado GC Green Tea, go fix modernizers - verificar parche en la compilación), chi (última - verificar en la compilación), gin (última - verificar en la compilación), echo (última - verificar en la compilación), google.golang.org/grpc (última - verificar en la compilación), sigs.k8s.io/controller-runtime (última - verificar en la compilación), kubebuilder (última - verificar en la compilación), tinygo (última - verificar objetivos de placa en la compilación), wazero (última - verificar en la compilación) y golangci-lint (última - verificar conjunto de linters en la compilación).
Revisado por Chris St. John·Última actualización: 19 jul 2026