Emitir
O problema imediato é que uma função do tipo func() Foo
não pode ser atribuída func() any
em Golang. Talvez esse seja um problema XY, então explicarei por que exatamente estou nessa situação.
Exemplo
Basicamente, tenho algo como um pacote de verificação de integridade (este é um modelo simplificado para simplificar):
//package: internal/health
type Check struct {
Name string
Func func() (metadata any, err error)
}
type Manager struct {
checks []Check
}
func (m *Manager) RegisterCheck(check Check) {
m.checks = append(m.checks , check)
}
func (m *Manager) PrintHealth() {
for _, check := m.checks {
output, _ := check.Func()
slog.Info("Health", slog.Any("output", output))
// In the actual implementation, I aggregate the checks and JSONify them
}
}
Então talvez eu tenha outro pacote que tenha métodos que eu queira adicionar às verificações:
//package: internal/service
type Foo struct {}
func (f Foo) Health() (string, error) {
return "baz", nil
}
type Bar struct {}
func (b Bar) Health() (map[string]int, error) {
return map[string]int{"qux": 1} , nil
}
//package: cmd/app
func main() {
foo := service.Foo{}
bar := service.Bar{}
h := health.Manager{}
h.RegisterCheck(health.Check{
Name: "Foo",
Func: foo.Health, // This is where the type error occurs
})
h.RegisterCheck(health.Check{
Name: "Bar",
Func: bar.Health, // This is where the type error occurs
})
}
O que eu tentei/considerei?
- Adicionar parâmetro de tipo para
Manager
eCheck
- Problema?
Manager
só seria capaz de adicionar verificações de um determinado tipo, o que significaria queFoo
eBar
não seria capaz de ser adicionado ao mesmoManager
, que é essencialmente compartilhado por todo o aplicativo.
- Problema?
- Adicionar parâmetro de tipo para
RegisterCheck
eCheck
- Problema? Golang não suporta parâmetros de tipo para métodos.
A solução mais simples é definir as funções de saúde para conformar a assinatura da interface:
Se o objetivo for simplesmente registrar o valor de retorno, isso deve funcionar.
Se você quiser manter os tipos de retorno, a próxima opção é usar adaptadores: