The immediate issue is that a function of type func() Foo
cannot be assigned func() any
in Golang. Perhaps this is an XY problem, so I will explain why exactly I am even in this situation.
I essentially have something like a health check package as such (this is a simplified model for sake of simplicity):
//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
}
}
Then perhaps I have another package that has a methods which I want to add to checks:
//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
})
}
Manager
and Check
Manager
would only become able to add checks of a certain type, so that would mean that Foo
and Bar
would not be able to be added to the same Manager
, which is essentially shared by the entire application.RegisterCheck
and Check
The simplest solution is to define the Health functions to conform the interface signature:
func (f Foo) Health() (any, error) {
return "baz", nil
}
func (b Bar) Health() (any, error) {
return map[string]int{"qux": 1} , nil
}
If the purpose is simply to log the return value, this should work.
If you want to keep the return types, then the next option is to use adapters:
h.RegisterCheck(health.Check{
Name: "Foo",
Func: func() (any,error) {
return foo.Health()
},
})
h.RegisterCheck(health.Check{
Name: "Bar",
Func: func() (any,error) {
return bar.Health()
},
})