简体   繁体   中英

how to send any function through a channel in golang?

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?

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

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM