Keywords like go and defer expect a function call as parameters. Is there a type available that can be used the same way? (e.g. to write a function that expects a function call - opposed to a function - as argument).
No there is not. You can't do the same with your function.
go and defer are backed by the language spec and the rule is enforced by the compiler.
What you may do is use a variable / value of function type, which you may call later / at any time as if it would be a function.
For example:
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
}
Edit: To have the functionality you mentioned in the comment: just wrap the function call with its arguments in a func(), and use / pass that.
For example:
func launch(f func()) {
fmt.Println("Before launch")
go func() {
defer fmt.Println("After completion")
f()
}()
}
Using it:
func main() {
launch(func() {
fmt.Println("Hello, playground")
})
time.Sleep(time.Second)
}
Which outputs (try it on the Go Playground):
Before launch
Hello, playground
After completion
Yes, this is not an exact workaround. If the params may change, you have to make a copy of them before calling launch(), and use the copy in the function literal (closure), like in this example:
s := "Hello, playground"
s2 := s // make a copy
launch(func() {
fmt.Println(s2) // Use the copy
})
s = "changed"
Mimicing automatic parameter saving
For a concrete function type we may construct a helper function which provides us automatic parameter saving. This helper function must have identical signature, and return a function without parameters. The returned function is a closure which calls the original function with the parameters. The act of calling this helper function is the mechanism to save the parameters, so the usage is identical to that of defer.
For example the helper for fmt.Println(s) is:
func wrapPrintln(s string) func() {
return func() {
fmt.Println(s)
}
}
And using it:
launch(wrapPrintln(s))
Example for a function with 2 int parameters:
func Sum(a, b int) {
fmt.Println("Sum:", a+b)
}
func WrapSum(a, b int) func() {
return func() {
Sum(a, b)
}
}
launch(WrapSum(a, b))
The above WrapPrintln() and WrapSum() wrapped a concrete function, and it can't be used for other functions (the wrapped function is "wired in"). We can make the wrapped functions a parameter too:
func WrapFuncIntInt(f func(a, b int), a, b int) func() {
return func() {
f(a, b)
}
}
And we may use it like this:
launch(WrapFuncIntInt(Sum, a, b))
Try this one on the Go Playground.
Using reflection to avoid the manual copies
You may use reflection to avoid having to make manual copies, but in this solution we're not actually calling the function, just passing it. Also due to using reflection, it will be slower. Another advantage is that this "feels" generic (we may use functions with different signatures), but we lose compile-time safety.
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)
}()
}
Example calling it:
func main() {
i, s := 1, "Hello, playground"
launch(fmt.Printf, "%d %q\n", i, s)
i, s = 2, "changed"
time.Sleep(time.Second)
}
Which outputs (try it on the Go Playground):
Before launch
1 "Hello, playground"
After completion
Single exception where you can utilize automatic parameter saving
There is a single exception which we may use. This is the Method value. If x has static type T and T's method set contains the method M, we may use x.M (without calling it).
The expression x.M is a method value, and it saves a copy of x which will be used as the receiver when the expression's result (which is a function value) is called.
Example:
type myParams struct {
format string
i int
s string
}
func (mp myParams) Call() {
fmt.Printf(mp.format, mp.i, mp.s)
}
func main() {
p := myParams{format: "%d %q\n", i: 1, s: "Hello, playground"}
launch(p.Call) // p is saved here
p.i, p.s = 2, "changed"
time.Sleep(time.Second)
}
func launch(f func()) {
fmt.Println("Before launch")
go func() {
defer fmt.Println("After completion")
f()
}()
}
It outputs the same. Try it on the Go Playground.
Related
(question reworded based on discussion, original question below)
The Go Language Specification gives examples showing that order of evaluation for primitives is unspecified with respect to function calls during assignment to slices and maps. None of the examples mention multi-value return though, so I'm not sure if they apply in this case or not.
Examples from the spec
a := 1
f := func() int { a++; return a }
x := []int{a, f()} // x may be [1, 2] or [2, 2]: evaluation order between a and f() is not specified
m := map[int]int{a: 1, a: 2} // m may be {2: 1} or {2: 2}: evaluation order between the two map assignments is not specified
n := map[int]int{a: f()} // n may be {2: 3} or {3: 3}: evaluation order between the key and the value is not specified
Using the language of the spec, is this functions return also unspecified:
func run() (int, int) {
a := 1
f := func() int { a++; return a }
return a, f() // always return 1,2 OR always returns 2,2 OR can return either?
}
If the order of evaluation is not specified then a non-toy example like the following could break at some time in the future if the compiler is updated:
func CountRows(ctx context.Context, db *pgxpool.Pool) (int, error) {
row := db.QueryRow(ctx, "SELECT COUNT(*)")
var count int
return count, row.Scan(&count)
}
Original Question
I'm unclear whether the go language specification is clear on whether values returned from funcs are "returned" one at a time or once all expressions are evaluated.
Aka is this code guaranteed to always output 10 <nil> (as it does in the playground) or can it ever output 0 <nil>?
package main
import "fmt"
func main() {
fmt.Println(run())
// Output: 10 <nil>
}
func run() (int, error) {
var i int
return i, inc(&i)
}
func inc(i *int) error {
*i = *i + 10
return nil
}
Edit
This related question suggests that order of evaluation of the primitive return value is not specified by the specification
"Is this function return also unspecified?"
Yes. As you found, the language specifies the evaluation order for some things:
when evaluating the operands of an expression, assignment, or return statement, all function calls, method calls, and communication operations are evaluated in lexical left-to-right order.
Naturally, anything that is not a function call, method call or communication operation is left unspecified with respect to evaluation order in an expression, assignment or return statement.
"a non-toy example like the following could break at some time in the future if the compiler is updated"
Yes. Even if the compiler doesn't update. If you expect it to have any particular result that's reliant on evaluation order, then the code is already broken in the sense that the language does not say the code will do what you think it will do.
"are values returned from funcs "returned" one at a time or once all expressions are evaluated."
There is no such distinction to be made.
"is this code guaranteed to always output 10 <nil> (as it does in the playground) or can it ever output 0 <nil>?"
Yes, it can output 0, <nil>. This is essentially the same as the previous run example, where now the closure f has been refactored as a function called inc.
Yes! This is a really great question.
Another way to write this code is
package main
import "fmt"
func main() {
fmt.Println(run())
// Output: 10 <nil>
}
func run() (int, error) {
var i int
err := inc(&i)
return i, err
}
func inc(i *int) error {
*i = *i + 10
return nil
}
This is the same reason why you can do the following
func main() {
callIt()
}
func callIt() (int, error) {
return multiReturn()
}
func multiReturn() (int, error) {
return 0, nil
}
And additionally, you can do this as well, which can be useful if you wrap a db transaction (for example) in an error handler
func main() {
result, err := assignInReturn()
if err != nil {
panic(err)
}
// the result here, assuming no error occurred, will be 1...
fmt.Println(result)
}
func assignInReturn() (int, error) {
var i int
return i, wrapErrFunc(func() error {
// db call
if err := dbCall(); err != nil {
return err
}
i = 1 // ...because of this. This will set `i` to 1 before `assignInReturn` returns to its caller
return nil
})
}
func wrapErrFunc(fn func() error) error {
return fn()
}
func dbCall() error {
// db query
return nil
}
In these situations, you can be certain that the items in the top-level return will evaluate prior to being returned to its caller
I have a goroutine inside a loop and I want to execute a goroutine for each item in ms.Entries concurrently but it's only running for the last item in the loop.
I've abstracted my example out of a larger program...
https://play.golang.org/p/whUMQ3pjq81
package main
import (
"fmt"
"sync"
)
type MyStruct struct {
Entry *Entry
Entries *[]Entry
}
type Entry struct {
ID int
Name string
}
type Fn struct {
Res string
Err error
}
func main() {
e1 := Entry{ID: 1, Name: "First"}
e2 := Entry{ID: 2, Name: "Second"}
ms := &MyStruct{
Entries: &[]Entry{e1, e2},
}
fmt.Printf("MS: %+v\n", ms)
var wg sync.WaitGroup
fnChan := make(chan *Fn)
go func() {
wg.Wait()
close(fnChan)
}()
var fns []func() (string, error)
fns = append(fns, ms.actionA)
fns = append(fns, ms.actionB)
for i, entry := range *ms.Entries {
fmt.Printf("%d: %+v\n", i, entry)
ms.Entry = &entry
for j, fn := range fns {
fmt.Printf("fn loop %d\n", j)
wg.Add(1)
go ms.process(&wg, fn, fnChan)
}
}
for d := range fnChan {
fmt.Printf("fnchan: %+v\n", d)
}
}
func (m *MyStruct) actionA() (string, error) {
fmt.Println("actionA")
fmt.Printf("Entry: %s\n", m.Entry.Name)
return "actionA done", nil
}
func (m *MyStruct) actionB() (string, error) {
fmt.Println("actionB")
fmt.Printf("Entry: %s\n", m.Entry.Name)
return "actionB done", nil
}
func (m *MyStruct) process(wg *sync.WaitGroup, fn func() (string, error), fnChan chan<- *Fn) {
fmt.Println("processing")
var err error
defer wg.Done()
res, err := fn()
if err != nil {
fnChan <- &Fn{Err: err}
return
}
fnChan <- &Fn{Res: res}
}
You have been caught by this trap : Using goroutines on loop iterator variables
One way to fix this :
for j, fn := range fns {
fmt.Printf("fn loop %d\n", j)
wg.Add(1)
// copy the iterator variable to a local variable :
// variables declared within the body of a loop are not shared between iterations
f := fn
go ms.process(&wg, f, fnChan)
}
Problem
You have a problem here:
ms.Entry = &entry
When you use a loop, like this:
for i, entry := range *ms.Entries {
The variable "entry" is only declared once.
So &entry will have a constant value (same value in every iteration).
But even if you solve that issue, another problem is that you are using the same ms object on every iteration.
So when you then launch different goroutines, the ms.Entry = ... statement you execute on the second iteration is modifying the shared ms object.
You are also "sharing" the fn variable between iterations as described in the other answer, so you should also capture that variable.
Fix
I suggest you remove the Entry field from your struct (you don't need it since you already have the complete array), and you use the array position to refer to the current entry.
You should add an i int parameter to your "action" and "process" functions.
You also need to "capture" the fn variable.
for i, entry := range *ms.Entries {
...
for j, fn := range fns {
...
fn := fn // capture the fn variable
go ms.process(&wg, fn, fnChan, i) // sending index here
}
}
See here for a modified playground:
https://play.golang.org/p/uuw7r4kGBPb
Can anyone explain why 0's and 1's are printed and not anything else? Thank you!
func makeFunction(name string) func() {
fmt.Println("00000")
return func() {
makeFunction2("abcef")
}
}
func makeFunction2(name string) func() {
fmt.Println("11111")
return func() {
makeFunction3("safsf")
}
}
func makeFunction3(name string) func() {
fmt.Println("33333")
return func() {
fmt.Printf("444444")
}
}
func main() {
f := makeFunction("hellooo")
f()
}
Can anyone explain why 0's and 1's are printed and not anything else? Thank you!
Let's follow the program flow:
main starts.
main calls makeFunction.
makeFunction prints 00000, and returns an anonymous function.
Back in main, we call the anonymous function returned by the previous call.
The anonymous function calls makeFunction2.
makeFunction2 prints 11111, and returns an anonymous function.
main returns.
Because the return value is discarded after step 6 above, nothing else is printed.
Let's look at your main:
Line 1
f := makeFunction("hellooo")
Side effect: printing "00000"
Return value: an anonymous function that executes makeFunction2("abcef"), assigned to the identifier f
Line 2
f()
which is equivalent to:
_ = f()
Side effect: printing "11111"
Return value: an anonymous function that executes makeFunction3("safsf"), discarded (you are not assigning the return value of f()).
makeFunction3 is never assigned to any identifier, and never called.
To prints the 3's, you have to call twice:
f()()
And to prints the 4's too, just do:
f()()()
Because ...
// prints "00000" and returns a function that if run
// will invoked `makeFunction2`
f := makeFunction("hello")
// `makeFunction2` is called, printing "11111" and returns
// a function that if run will invoked `makeFunction3`
f1 := f()
// `makeFunction3` is called, printing "33333" and returns
// a function that if run will invoked `makeFunction4`
f2 := f1()
Test question, what does it print out if you do this?
f := makeFunction("Hello")()()
f()
This is known as currying or closure, but in your example you have not closed over any local value so the latter loses its meaning.
makeFunction only return the function makeFunction2. since this is not a recursive function. If you expecting to behave like recursive function, then you should change return func(){} to (return makeFunction2 or 3)
func makeFunction(name string) func() {
fmt.Println("00000")
return makeFunction2("abcef")
}
func makeFunction2(name string) func() {
fmt.Println("11111")
return makeFunction3("safsf")
}
func makeFunction3(name string) func() {
fmt.Println("33333")
return func() {
fmt.Printf("444444")
}
}
func main() {
f := makeFunction("hellooo")
f()
}
// Output:
00000
11111
33333
444444
The Reason is it only returns the anonymous funtions.
package main
import "fmt"
func makeFunction(name string) func() {
fmt.Println("00000")
return func(){
makeFunction2("abcef")()
}
}
func makeFunction2(name string) func() {
fmt.Println("11111")
return func() {
makeFunction3("safsf")()
}
}
func makeFunction3(name string) func() {
fmt.Println("33333")
return func() {
fmt.Printf("444444")
}
}
func main() {
f := makeFunction("hellooo")
f()
}
I am trying to loop a slice of function and then invoke every function in it. However I am getting strange results. Here is my code:
package main
import (
"fmt"
"sync"
)
func A() {
fmt.Println("A")
}
func B() {
fmt.Println("B")
}
func C() {
fmt.Println("C")
}
func main() {
type fs func()
var wg sync.WaitGroup
f := []fs{A, B, C}
for a, _ := range f {
wg.Add(1)
go func() {
defer wg.Done()
f[a]()
}()
}
wg.Wait()
}
I was thinking that it will invoke function A,B and then C but my output gets only Cs.
C
C
C
Please suggest whats wrong and the logic behind it. Also how can I get desired behavior.
Go Playground
Classic go gotcha :)
Official Go FAQ
for a, _ := range f {
wg.Add(1)
a:=a // this will make it work
go func() {
defer wg.Done()
f[a]()
}()
}
Your func() {}() is a closure that closes over a. And a is a shared across all the go func go routines because for loop reuses the same var (meaning same address in memory, hence same value), so naturally they all see last value of a.
Solution is either re-declare a:=a before closure (like above). This will create new var (new address in memory) which is then new for each invocation of go func.
Or pass it in as parameter to the go function, in which case you pass a copy of value of a like so:
go func(i int) {
defer wg.Done()
f[i]()
}(a)
You don't even need to have go routines this https://play.golang.org/p/nkP9YfeOWF for example demonstrates the same gotcha. The key here is 'closure'.
The problem seems to be that you are not passing the desired value to the goroutine and the variable value is being taken from the outer scope. That being said, the range iteration finishes even before the first goroutine is executed and that is why you are always getting index a == 2, which is function C.
You can test this if you simply put time.Sleep(100) inside your range, just to allow the goroutine to catch up with the main thread before continuing to the next iteration --> GO playground
for a, _ := range f {
wg.Add(1)
go func() {
defer wg.Done()
f[a]()
}()
time.Sleep(100)
}
Output
A
B
C
Although what you want to do is just simply pass a parameter to the goroutine which will make a copy for the function.
func main() {
type fs func()
var wg sync.WaitGroup
f := []fs{A, B, C}
for _, v := range f {
wg.Add(1)
go func(f fs) {
defer wg.Done()
f()
}(v)
}
wg.Wait()
}
GO Playground
I am a Go beginner, coming from Ruby land.
In Ruby, you could do something like this.
Time.send("now") is equivalent to Time.now, as you are sending the message now to the object Time
Is there something similar in golang?
There is no built in way of calling an arbitrary function from a string in Go.
You can create something similar by registering functions to a map[string].
A working example:
package main
import "fmt"
var m = map[string]func(){
"now": func() { fmt.Println("The time is now") },
"then": func() { fmt.Println("Once upon a time") },
}
func main() {
cmd := "then"
m[cmd]()
}
play.golang.org
There is also the possibility of using reflection in order to call a method by name. You can look at the reflect package for MethodByName and Call. You can also check this Stackoverflow question.
As other suggested, you can do it yourself by mapping strings to functions, but the strong-typing nature of Go makes it difficult to translate .send directly into Go.
You can still use reflection if you really need to access a field or method by name:
import "reflect"
import "fmt"
type A struct {
Number int
}
func (a *A) Method(i int) int {
return a.Number + i;
}
func main() {
a := &A{Number: 1}
// Direct access
fmt.Printf("Direct -> Nb: %d, Nb + 2: %d\n", a.Number, a.Method(2));
v := reflect.ValueOf(*a)
vp := reflect.ValueOf(a)
field := v.FieldByName("Number")
meth := vp.MethodByName("Method")
args := []reflect.Value{reflect.ValueOf(2)}
// Reflection access
fmt.Printf("Reflect -> Nb: %d, Nb + 2: %d\n",
field.Interface().(int),
meth.Call(args)[0].Interface().(int))
}
Outputs:
Direct -> Nb: 1, Nb + 2: 3
Reflect -> Nb: 1, Nb + 2: 3
play.golang.org
Note however:
How cumbersome that is. Usually, performing a map as suggested by #ANisus is a more idiomatic way of doing
You still have to perform your conversions in the end.
Using the reflect packages changes your typed variable into more flexible Value objects, but these are very cumbersome to use in practice. It is usually better if you can find a way to express your intent without relying on reflection.
Also note that here, we had to use two Values, one for a (a pointer to A) for the method, and one for *a (a A structure) for the field. Trying to get a method defined with a pointer receiver with a non-pointer Value (or conversely, trying to obtain a field via a pointer Value) will result in a panic. More generally, due to the dynamic nature of reflected Values and its difference with the usual typed Go, expect a lot of convenience features (such as automatic referencing/dereferencing) to be absent on Values.
Also, expect quite a bit of runtime panics while debugging, as it is the only way for dynamic Value calls to fail !
Reference: the reflect package
No. Work your way through http://tour.golang.org/ and http://golang.org/doc/effective_go.html and you will have a proper understanding of how method invocation works.
Here is a working example using reflect
package main
import (
"fmt"
"os"
"reflect"
)
// Send sends a message to(calls a method of) obj, with args.
// The return value of the method call is set to ret and any error to err.
func Send(obj interface{}, method string, args ...interface{}) (ret []reflect.Value, err error) {
defer func() {
if e := recover(); e != nil {
err = fmt.Errorf("%v", e)
}
}()
objValue := reflect.ValueOf(obj)
argsValue := make([]reflect.Value, 0, len(args))
for _, arg := range args {
argsValue = append(argsValue, reflect.ValueOf(arg))
}
mtd := objValue.MethodByName(method)
if !mtd.IsValid() {
return nil, fmt.Errorf("%v does not have a method %v", reflect.TypeOf(obj), method)
}
ret = mtd.Call(argsValue)
return
}
// Then do some tests.
type A struct {
value int
}
func (a A) Value() int {
return a.value
}
func (a *A) SetValue(v int) {
a.value = v
}
func main() {
var (
ret []reflect.Value
err error
)
// StdOut.WriteString("Hello, World!\n")
_, err = Send(os.Stdout, "WriteString", "Hello, World!\n")
handleError(err)
var a = &A{100}
// ret = a.Value()
ret, err = Send(a, "Value")
handleError(err)
fmt.Printf("Return value is: %v\n", ret[0].Int())
// a.SetValue(200)
_, err = Send(a, "SetValue", 200)
handleError(err)
// ret = a.Value()
ret, err = Send(a, "Value")
handleError(err)
fmt.Printf("Return value is: %v", ret[0].Int())
}
func handleError(err error) {
if err != nil {
panic(err)
}
}
I based my code on this description of send.
class Klass
def hello(*args)
"Hello " + args.join(' ')
end
end
k = Klass.new
k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
http://play.golang.org/p/lXlzBf_fGZ
package main
import "strings"
type Klass struct{}
func (k Klass) Hello(args ...string) string {
return "Hello " + strings.Join(args, " ")
}
func (k Klass) Send(symbol func(Klass, ...string) string, args ...string) string {
return symbol(k, args...)
}
func main() {
k := new(Klass)
k.Send(Klass.Hello, "gentle", "readers") //=> "Hello gentle readers"
}
The big difference between the two is that Go's Send function is only implemented for Klass and only works on methods that take a variable number of strings as parameters and return a single string. This is because Go is a statically typed language where Ruby is dynamically typed. Go does support dynamic typing via the reflect library, but it is an unpleasant experience and not the way general Go code is meant to be written.