и хочется этого избежать. Ок, пишем обертку с контекстом, но возникает проблема, что получается утечка, если таймаут сработал, а функция зависла. Как можно этого избежать?
Вот код:
func main() {
ctx, _ := context.WithTimeout(context.Background(), 100*time.Millisecond)
err := sendWithContext(ctx, "Hello, world!")
if err != nil {
fmt.Println(runtime.NumGoroutine())
log.Fatal(err)
}
fmt.Println(runtime.NumGoroutine())
}
// Функция без контекста (плохая)
func send(msg string) error {
fmt.Println("Sending message:", msg)
time.Sleep(10 * time.Minute) // Имитация долгой операции
return nil
}
// Попытка добавить контекст в функцию.
func sendWithContext(ctx context.Context, msg string) error {
errCh := make(chan error, 1)
go func() { // При срабатывании таймаута эта горутина подолжает висеть
errCh <- send(msg)
}()
select {
case <-ctx.Done():
return errors.New("sendWithContext: operation timed out")
case err := <-errCh:
return err
}
}
плейграунд: https://goplay.space/#_5umb1Vmvsz
так select case с чтением Done() в горутине пишется, а не в функции рядом 🙂
Обсуждают сегодня