Waiting for the result of several Horus

I am looking for a way to execute asynchronously two functions in go, which returns different results and errors, waiting for them to complete and print both results. Also, if one of the functions returned an error, I do not want to wait for another function and just print the error. For example, I have the following 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 I have too much code, I think. It can be simplified using the {} interface, but I don’t want to go that route. I want something simpler, for example, in C # can be implemented using async / await. There is probably some library that simplifies such an operation.

: ! , ! WaitGroup. , , , async . , - #. , go async, , , , , , , async, json, go -kit.

+4
3

, , erorrs , :

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, " ------------")
    }
}
+2

, sync.WaitGroup. .

+3

, , , , (. ):

package main

import (
    "errors"
    "fmt"
    "math/rand"
    "time"
)

func main() {
    rand.Seed(time.Now().UnixNano())

    // buffer the channel so the async go routines can exit right after sending
    // their error
    status := make(chan error, 2)

    go func(c chan<- error) {
        if rand.Intn(2) == 0 {
            c <- errors.New("func 1 error")
        } else {
            fmt.Println("func 1 done")
            c <- nil
        }
    }(status)

    go func(c chan<- error) {
        if rand.Intn(2) == 0 {
            c <- errors.New("func 2 error")
        } else {
            fmt.Println("func 2 done")
            c <- nil
        }
    }(status)

    for i := 0; i < 2; i++ {
        if err := <-status; err != nil {
            fmt.Println("error encountered:", err)
            break
        }
    }
}

, . . nil, .

At the end, I read one value for each async go procedure from the channel. This blocks until a value is received. If an error occurs, I exit the loop, thereby leaving the program.

Functions are performed or are performed randomly.

I hope you will understand how to coordinate the programs, if not, let me know in the comments.

Note , if you run this on the Go playground, rand.Seed will not do anything, the playground will always have the same "random" numbers, so the behavior will not change.

0
source

Source: https://habr.com/ru/post/1688068/


All Articles