在其最简单的形式中,更好的抽象是为处理程序使用简单func()
类型,如果需要参数,调用者应该传递一个捕获所需参数的闭包。所以你根本不必关心它们,也不必求助于反射。
允许这些函数报告成功或失败是合理且可取的,因此请使用函数类型func() error
。
一个可能的实现:
type Task struct {
handler func() error
}
func (t *Task) execute() {
if err := t.handler(); err != nil {
fmt.Println("Failed to execute task:", err)
}
}
现在让我们创建示例作业:
func simpleJob() error {
fmt.Println("simple")
return nil
}
func complexJob(s string) {
fmt.Println("complex", s)
}
这就是我们如何在Task
s 中使用它们:
t := &Task{handler: simpleJob}
t.execute()
t = &Task{handler: func() error {
complexJob("data")
return nil
}}
t.execute()
哪些输出(在Go Playground上尝试):
simple
complex data
我们很“幸运” simpleJob()
:它的签名与我们需要的处理程序相匹配,所以我们可以按原样使用它。不像complexJob()
which 有一个完全不同的签名:它有一个string
参数并且不返回一个error
,但是使用匿名函数(一个闭包)我们仍然可以将它用于Task.handler
.
如果作业需要更多的控制或报告功能,则应为它们创建适当的接口,并提交此类接口的值以供执行,而不仅仅是简单的功能。
例如:
type Job interface{
Execute() error
Progress() int
Result() interface{}
}
type Task struct {
job Job
}
func (t *Task) execute() {
if err := t.job.Execute(); err != nil {
fmt.Println("Failed to execute task:", err)
}
}