【问题标题】:Is there a way to handle generic function in go [duplicate]有没有办法在go中处理通用函数[重复]
【发布时间】:2020-01-15 14:47:56
【问题描述】:

我是新手,想实现一个接收任务的调度程序(即间隔 + 处理程序)。 我陷入了应该获取处理程序的部分,因为 go 是一种静态语言(我无法获得通用函数签名)。 我想出了以下解决方案: 每个“处理程序”函数都将被空接口包裹:

type GenericFunc interface{}
add_task(GenericFunc(my_func), p1, p2,...)

这将导致以下结构用于保存处理程序及其参数:

type Task struct {
   handler reflect.Value
   params []reflect.Value
   ...
}

任务执行将由以下人员调用:

func (t *Task) execute() {
    t.handler.Call(t.params)
}

我的问题是这是处理泛型函数的正确方法,还是我缺少更惯用的解决方案? 谢谢。

【问题讨论】:

  • 提供的所有链接都不能解决这里提出的问题。另外,我认为最好删除重复的 cmets,因为人们实际上可能会使用这些信息。
  • 如果您认为重复的链接不能回答您的问题,请解释原因。根据我的阅读,它们是直接适用的。

标签: go generic-method reflect


【解决方案1】:

在其最简单的形式中,更好的抽象是为处理程序使用简单的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)
}

这就是我们可以在Tasks 中使用它们的方式:

t := &Task{handler: simpleJob}
t.execute()

t = &Task{handler: func() error {
    complexJob("data")
    return nil
}}
t.execute()

哪些输出(在Go Playground 上试试):

simple
complex data

simpleJob() 我们很“幸运”:它的签名与我们需要的处理程序相匹配,因此我们可以按原样使用它。不像complexJob() 具有完全不同的签名:它有一个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)
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-27
    • 2011-02-01
    • 2015-08-04
    • 1970-01-01
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多