I want to implement an executor like below:
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)
}
Then, I want to wrap any function into task type, like this pseudo code:
func make_task(f function_addr, args ...interface{}) task{
return func(){
f(args...)
}
}
How can I achieve this?
CodePudding user response:
You can't write a generic function to do what you want, but you can do what you need using closures like:
executor.Push(func() {
someFunc(arg1,arg2,...)
})
where arg1
, arg2
, etc. are arguments available at that point in code.
CodePudding user response:
The simple approach is to use a function literal in place of make_task:
t := func() { exampleFunction(exampleArg1, exampleArg2) }
e.Push(t)
If the simple approach does not fit into your application for some reason, then use the reflect package to call an arbitrary function with arbitrary arguments:
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)
}
}
Example:
func hello(arg string) {
fmt.Println("Hello", arg)
}
…
t := make_task(hello, "world")
t() // prints Hello world