Funções Variádicas e Tipos de Função
Go trata funções como valores que você pode nomear, passar e retornar - e permite que o último parâmetro absorva uma lista de argumentos variável com ...T.
Busque em todas as páginas da documentação
Go trata funções como valores que você pode nomear, passar e retornar - e permite que o último parâmetro absorva uma lista de argumentos variável com ...T.
Juntos, assinaturas variádicas e tipos de função potencializam middleware, opções e pequenos pontos de extensão sem a verbosidade de interfaces.
Um parâmetro variádico (args ...int) é açúcar sintático para um slice dentro da função.
Chamadores passam zero ou mais argumentos, ou expandem um slice existente com fn(slice...).
Um tipo de função (type Handler func(...)) documenta contratos chamáveis e habilita funções de ordem superior que aceitam comportamento como dados.
Use variádicas para construtores como fmt.Sprintf, auxiliares de log e opções funcionais.
Use tipos de função para middleware HTTP, wrappers de retentativa e predicados.
Prefira interfaces pequenas quando precisar de múltiplos métodos relacionados ou mocking entre pacotes.
Cartão de receita de referência rápida - pronto para copiar e colar.
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)
})
}Quando usar isso:
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")O que isso demonstra:
AttemptFunc nomeia o contrato chamável em vez de repetir func(context.Context) error.Do de ordem superior aceita comportamento e gerencia a política de loop/backoff.ExampleUsage adapta um call mais simples para AttemptFunc.... no local da chamada "espalha" um slice em argumentos discretos.func(int) int a type Op func(int) int sem conversão, mas a conversão é permitida quando as assinaturas coincidem.nil devem ser verificados antes da chamada - invocar nil causa pânico como uma chamada de método de interface nil.| Regra | Detalhe |
|---|---|
| Posição | Parâmetro variádico deve ser o último |
| Dentro do corpo | Tipo é []T, use len, range normalmente |
| Zero args | Válido - slice é não-nil, comprimento 0 |
| Espalhamento | fn(slice...) requer tipo de slice []T exatamente |
| Mistura | Não pode passar argumento não-variádico após captura variádica |
| Mecanismo | Força | Limite |
|---|---|---|
Tipo func | Um método, zero boilerplate | Nenhum agrupamento multi-método nomeado |
| Interface | Mocking, evolução via embedding | Test doubles mais amplos |
| Generics + func | Algoritmos reutilizáveis | Assinaturas mais pesadas |
var fn func()
if fn != nil {
fn()
}Sempre proteja callbacks opcionais.
Cadeias de middleware devem tratar nil como identidade: if mw == nil { return next }.
if fn != nil antes de invocar, ou exija não-nil na documentação da API.args == nil é falso para chamada de zero argumentos (slice vazio não-nil). Correção: use len(args) == 0 quando distinguir ausente vs vazio for importante.[]byte não pode ser "espalhado" para ...int. Correção: converta ou altere a assinatura.New.Op(fn) quando necessário.CallSlice. Correção: atenha-se a chamadas tipadas, a menos que esteja construindo ferramentas genéricas.
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| Interface pequena | Múltiplos métodos, mocks gerados | Hook único estilo ServeHTTP |
| Opções de struct | Necessita validação entre campos | Apenas um ou dois "knobs" |
Padrão Builder (Chain().Use()) | Registro de middleware fluente | Slice []Middleware simples é suficiente |
Generics func F[T any](...) | Utilitários de map/filter type-safe | Carregamento de plugins em tempo de execução |
Declara um parâmetro variádico do tipo slice []T.
A função recebe todos os argumentos finais como um único slice.
Use fn(items...) onde items é []T.
Sem ..., você passa o slice como um único argumento (erro de tipo se a assinatura for variádica).
Sim - a menos que você valide len(args) == 0 e retorne um erro.
fmt.Println() é um exemplo familiar.
Um tipo nomeado cujo tipo subjacente é uma assinatura de função.
Permite métodos em funções (veja http.HandlerFunc) e APIs mais claras.
Injete AttemptFunc ou funções de relógio para simular falhas sem interfaces.
Testes passam closures que gravam invocações.
func(http.Handler) http.Handler é o padrão do ecossistema para net/http.
gRPC usa tipos de função de interceptador de forma semelhante.
O cabeçalho do slice é passado por valor; os elementos são referenciados.
Mutar args[0] dentro da função afeta os elementos do chamador se eles compartilharem o array de backing.
Sim - receptores coexistem com parâmetros variádicos: func (l *Logger) Info(msg string, kv ...any).
Opções escalam campos opcionais sem quebrar chamadores.
Configuração obrigatória grande ainda se encaixa em uma struct validada uma vez em New.
Não - use opções funcionais, structs de configuração ou wrappers de estilo de sobrecarga (Dial() chamando DialContext(context.Background(), ...)).
Sim - o tipo de valor é a assinatura da função ou o tipo nomeado.
Lembre-se que chaves de mapa não podem ser slices; chaves devem ser comparáveis.
Generics reduzem a duplicação para algoritmos de slice; tipos de função ainda expressam injeção em tempo de execução e hooks de I/O.
HandlerFunc)Versões de Stack: Esta página foi escrita para Go 1.26.x (padrão GC Green Tea, go fix modernizers - verifique o patch na compilação), chi (última - verifique na compilação), gin (última - verifique na compilação), echo (última - verifique na compilação), google.golang.org/grpc (última - verifique na compilação), sigs.k8s.io/controller-runtime (última - verifique na compilação), kubebuilder (última - verifique na compilação), tinygo (última - verifique os alvos de placa na compilação), wazero (última - verifique na compilação) e golangci-lint (última - verifique o conjunto de linters na compilação).
Revisado por Chris St. John·Última atualização: 19 de jul. de 2026