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 шт):
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 предпочтителен, так как можем обработать ситуацию, когда в канали ничего не пришло.