【问题标题】:how to send any function through a channel in golang?如何通过golang中的通道发送任何功能?
【发布时间】:2022-01-06 00:02:02
【问题描述】:

我想实现一个像下面这样的执行器:

type task func()

type executor struct {
    tasks chan task
}

func (e *executor) Push(t task) {
    select {
    case e.tasks <- t:
    default:
        return
    }
}
func (e *executor) Run() {
    for {
        select {
        case t := <-e.tasks:
            t()

        }
    }
}
func (e *executor) Init() {
    e.tasks = make(chan task, 10)
}

然后,我想将任何函数包装成任务类型,比如这个伪代码:

func make_task(f function_addr, args ...interface{}) task{
    return func(){
    f(args...)
}
}

我怎样才能做到这一点?

【问题讨论】:

  • 这是一件非常奇怪的事情。似乎您只是在go func(args) 之上发明了一个抽象层,以及一个缓冲通道形式的计数信号量。当 Go 专门为此目的为您提供 go 关键字时,通过通道发送函数及其参数以供 go 例程调用,您可以获得什么好处?

标签: go


【解决方案1】:

你不能编写一个通用函数来做你想做的事,但你可以使用像这样的闭包来做你需要做的事:

executor.Push(func() {
    someFunc(arg1,arg2,...)
 })

其中arg1arg2 等是代码中该点可用的参数。

【讨论】:

    【解决方案2】:

    简单的方法是使用function literal 代替make_task:

    t := func() { exampleFunction(exampleArg1, exampleArg2) }
    e.Push(t)
    

    如果由于某种原因简单方法不适合您的应用程序,则使用reflect 包调用带有任意参数的任意函数:

    func make_task(f interface{}, args ...interface{}) task {
        return func() {
            values := make([]reflect.Value, len(args))
            for i := range args {
                values[i] = reflect.ValueOf(args[i])
            }
            reflect.ValueOf(f).Call(values)
        }
    }
    

    例子:

    func hello(arg string) {
        fmt.Println("Hello", arg)
    }
    
    …
    
    t := make_task(hello, "world")
    t()  // prints Hello world
    

    https://go.dev/play/p/5b6VPfV45qo

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-20
      • 2019-08-16
      • 2021-10-08
      • 1970-01-01
      • 2020-08-20
      • 2018-08-13
      相关资源
      最近更新 更多