Go Type for Function Call
When utilizing keywords like go and defer, function calls are required as parameters. However, is there a specific type that can be used in a similar manner, particularly for creating a function that expects a function call (not simply a function itself) as an argument?
Limitations and Workarounds
Go does not provide a type that directly allows for this functionality. Instead, one can employ function-typed variables or values and call them later as if they were functions. For instance:
<code class="go">func myFunc() { fmt.Println("hi") } func main() { var f func() f = myFunc f() // This calls the function value stored in f: myFunc in this example }</code>
To achieve the desired functionality mentioned in the comment, wrap the function call and arguments within a func() and utilize that. For example:
<code class="go">func launch(f func()) { fmt.Println("Before launch") go func() { defer fmt.Println("After completion") f() }() }</code>
Usage:
<code class="go">func main() { launch(func() { fmt.Println("Hello, playground") }) time.Sleep(time.Second) }</code>
Output:
Before launch Hello, playground After completion
This method does not involve a direct workaround. If parameters change, make a copy before calling launch() and employ the copy within the function literal (closure).
Mimicking Automatic Parameter Saving
For a specific function type, create a helper function with identical signature, returning a function without parameters. The returned function acts as a closure, calling the original function with the parameters. Invoking the helper function effectively saves the parameters, mimicking the behavior of defer:
<code class="go">func wrapPrintln(s string) func() { return func() { fmt.Println(s) } }</code>
Usage:
<code class="go">launch(wrapPrintln(s))</code>
Using Reflection
Reflection can eliminate the need for manual copies, but this approach involves passing functions as parameters instead of calling them. It is also slower due to reflection overhead.
<code class="go">func launch(f interface{}, params ...interface{}) { fmt.Println("Before launch") go func() { defer fmt.Println("After completion") pv := make([]reflect.Value, len(params)) for i, v := range params { pv[i] = reflect.ValueOf(v) } reflect.ValueOf(f).Call(pv) }() }</code>
Example usage:
<code class="go">func main() { i, s := 1, "Hello, playground" launch(fmt.Printf, "%d %q\n", i, s) i, s = 2, "changed" time.Sleep(time.Second) }</code>
Output:
Before launch 1 "Hello, playground" After completion
Exception: Method Value
One exception where automatic parameter saving can be utilized is with method values. When x has static type T and T's method set contains method M, x.M (without calling it) represents a method value that captures a copy of x as the receiver when the expression's result (a function value) is called.
The above is the detailed content of Can Go directly represent function calls as a type for use as parameters?. For more information, please follow other related articles on the PHP Chinese website!