I am searching a way to execute asynchronously two functions in go which returns different results and errors, wait for them to finish and print both results. Also if one of function returned error I do not want to wait for another function, and just print the error. For example, I have this functions:
func methodInt(error bool) (int, error) {
<-time.NewTimer(time.Millisecond * 100).C
if error {
return 0, errors.New("Some error")
} else {
return 1, nil
}
}
func methodString(error bool) (string, error) {
<-time.NewTimer(time.Millisecond * 120).C
if error {
return "", errors.New("Some error")
} else {
return "Some result", nil
}
}
Here https://play.golang.org/p/-8StYapmlg is how I implemented it, but it has too much code I think. It can be simplified by using interface{} but I don't want to go this way. I want something simpler as, for example, can be implemented in C# with async/await. Probably there is some library that simplifies such operation.
UPDATE: Thank for your responses! It is awesome how fast I got help! I like the usage of WaitGroup. It obviously makes the code more robust to changes, so I easily can add another async method without changing exact count of methods in the end. However, there is still so much code in comparison to same in C#. I know that in go I don't need to explicitly mark methods as async, making them actually to return tasks, but methods call looks much more simple, for example, consider this link actually catching exception is also needed By the way, I found that in my task I actually don't need to know returning type of the functions I want to run async because it will be anyway marshaled to json, and now I just call multiple services in the endpoint layer of go-kit.
The WaitGroup type of sync package, is used to wait for the program to finish all goroutines launched from the main function. It uses a counter that specifies the number of goroutines, and Wait blocks the execution of the program until the WaitGroup counter is zero.
Goroutines are functions or methods that run concurrently with other functions or methods. Goroutines can be thought of as lightweight threads. The cost of creating a Goroutine is tiny when compared to a thread. Hence it's common for Go applications to have thousands of Goroutines running concurrently.
You can send the return value in a channel in the goroutine and then collect that value in the main function. This line will wait until a value is pushed to the result channel. As seen above the sumValue will be pushed to result channel by the function sum.
You should create two channels for errors and results, then first read errors if no erorrs then read the results, this sample should works for your use case:
package main
import (
"errors"
"sync"
)
func test(i int) (int, error) {
if i > 2 {
return 0, errors.New("test error")
}
return i + 5, nil
}
func test2(i int) (int, error) {
if i > 3 {
return 0, errors.New("test2 error")
}
return i + 7, nil
}
func main() {
results := make(chan int, 2)
errors := make(chan error, 2)
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
result, err := test(3)
if err != nil {
errors <- err
return
}
results <- result
}()
wg.Add(1)
go func() {
defer wg.Done()
result, err := test2(3)
if err != nil {
errors <- err
return
}
results <- result
}()
// here we wait in other goroutine to all jobs done and close the channels
go func() {
wg.Wait()
close(results)
close(errors)
}()
for err := range errors {
// here error happend u could exit your caller function
println(err.Error())
return
}
for res := range results {
println("--------- ", res, " ------------")
}
}
I think here sync.WaitGroup can be used. It can waits for different and dynamic number of goroutines.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With