- Anonymous functions are defined where they are used, do not need to have a name and lead to more compact code that is easier to understand.
- function.go is a simple program with a function definition and call.
- Its behavior is exactly as you would expect.
/* function.go */ package main import "fmt" func myFunc(i int){ fmt.Printf("hello from function %2d\n", i); } func main() { for i := 0; i < 10; i++ { myFunc(i) } }
The output of this program is:
hello from function 0 hello from function 1 hello from function 2 hello from function 3 hello from function 4 hello from function 5 hello from function 6 hello from function 7 hello from function 8 hello from function 9
- The program anonFunc.go demonstrates an anonymous function.
- Here the function is declared as and when required and is not given a name (hence anonymous).
- The arguments to the function are provided in the round brackets, (. . .) at the end of func.
/* anonFunc.go */ package main import "fmt" func main() { for i := 0; i < 10; i++ { func(i int){ fmt.Printf("hello from function %2d\n", i); }(i) } }
- The output is the same as before.
- By adding go before func, as shown in anonFuncGo.go (below), we can create a goroutine, so that 10 goroutines execute in concurrently.
- This program is incorrect as it does not use synchronization.
/* anonFuncGo.go (incorrect!)*/ package main import ( "fmt" ) func main() { for i := 0; i < 10; i++ { go func(i int){ fmt.Printf("hello from function %2d\n", i); }(i) } }
- If you run this program repeatedly using the command go run anonFuncGo.go you will get incomplete output.
- In some cases nothing is printed, in other cases incomplete output is obtained.
- This is caused by lack of synchronization.
- The correct program is as follows:
/* anonFuncGOCorrect.go */ package main import ( "fmt"; "sync" ) func main() { var wg sync.WaitGroup wg.Add(10) for i := 0; i < 10; i++ { go func(i int){ fmt.Printf("hello from function %2d\n", i); wg.Done() }(i) } wg.Wait() }
- In this case a synchronization variable wg is declared and initialized to 10.
- Whenever a goroutine func completes, wg is decremented by 1 using wg.Done().
- At the end the program waits for all goroutines to complete (i.e. wg to become 0) using wg.Wait().
- Here is a typical output:
hello from function 9 hello from function 2 hello from function 6 hello from function 5 hello from function 8 hello from function 4 hello from function 3 hello from function 1 hello from function 7 hello from function 0
- All 10 goroutines complete, but the order of execution is jumbled.
- This is because all goroutines are concurrent and we have no control over when one starts or finishes.
- If your run this program repeatedly, you will see that the order of completion of goroutines is different, but all 10 goroutrines will complete successfully.