问题
当前问题是Golang 中func() Foo
无法分配类型的函数func() any
。也许这是一个 XY 问题,所以我将解释为什么我处于这种情况。
例子
我本质上有类似健康检查包的东西(为了简单起见,这是一个简化的模型):
//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
}
}
然后也许我有另一个包,其中包含我想要添加到检查的方法:
//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
到Check
- 问题?
Manager
将只能添加特定类型的检查,这意味着Foo
和Bar
将无法添加到同一个Manager
,这实际上是由整个应用程序共享的。
- 问题?
- 将类型参数添加
RegisterCheck
到Check
- 问题?Golang 不支持方法的类型参数。
最简单的解决方案是定义 Health 功能以符合接口签名:
如果目的只是记录返回值,那么这应该可行。
如果您想保留返回类型,那么下一个选项是使用适配器: