Golang чтение бесконечного цикла горутины в родительском потоке

Есть горутина, в которой есть бесконечный цикл for {}, в нем происходит вызов http запроса, при вызове запроса может произойти ошибка, можно ли ее как-то поймать в родительской горутине, передав в канал, не блокируя ее ? То есть я создал канал errors := make(chan error, 1), передаю errors методу, который вызывается в горутине go someFunc(errors), если делать что-то вроде waitGroup или errorGroup, то основной поток будет заблокирован, пока someFunc не завершит работу, так что не подходит.

В коде это примерно так выглядит

func someMainFunc () error {
    errors := make(chan error, 1)
    go someFunc(errors)
    // тут нужно поймать ошибку из канала и вернуть ее из someMainFunc()
}

func someFunc(errorsChan chan error) {
    for {
        // do http request
        if err != nil {
            errorsChan <- err
            return
        }
    }
}

Ответы (1 шт):

Автор решения: Senior Pomidor
import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    errors := make(chan error, 1)
    go someFunc(errors)

    select {
    // тут пытаемся поймать ошибку. если она произошла, то попадет в канал errors и сработает этот триггер
    case err := <-errors:
        fmt.Printf("here error recieved. %v\n", err)

    // если вдруг ошибку не получили, то не хочется ждать бесконечно,
    // огриничиваем на 10 секунд, то есть эта секуция сработает почсле 10 секунд
    case <-time.After(10 * time.Second):
        fmt.Printf("here error did not recieved after 10 second")
    }

    // one more option
    // тут мы можем без select ждать ошибку пока не поймаем ее.
    err := <- errors
    fmt.Printf(err.Error())

}

func someFunc(errorsChan chan error) {
    for {
        err := doSomething()
        if err != nil {
            errorsChan <- err
            errorsChan <- fmt.Errorf("my custom error")
            return
        }
    }
}

func doSomething() error {
    time.Sleep(time.Second)
    if rand.Int()%5 == 0 {
        return fmt.Errorf("test error")
    }
    return nil
}

output:

here error recieved. test error
my custom error

https://play.golang.org/p/-OP82HJrwXe

я показал 2 способа поймать ошибку, в любом случае алгоритм простой. если есть канал и мы хотим вытянуть из него информацию, то это делается через <-, например, err := <- errors. Если в канал попадает несколько ошибок, то нужно несколько раз запрашивать ошибку.

выбор с Select предпочтителен, так как можем обработать ситуацию, когда в канали ничего не пришло.

→ Ссылка