Найти тему
2015 подписчиков

👣 Прервать функцию с горутинами, если выполняется слишком долго


▶️Задача: в функции нужно запустить несколько горутин с вычислениями и дождаться их окончания.
При этом, если функция будет работать больше указанного количества секунд, нужно прервать ее выполнение.
Таким образом нужно прервать выполнение этой функции fun() ниже, что можно сделать?

package main

import (
"fmt"
"sync"
)

func FibonacciRecursion(n int) int {
if n <= 1 {
return n
}
return FibonacciRecursion(n-1) + FibonacciRecursion(n-2)
}

func f(i int, wg *sync.WaitGroup) {
defer wg.Done()
fmt.Println(FibonacciRecursion(45 + i))
}

func fun() {
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
go f(i, &wg)
wg.Add(1)
}
wg.Wait()
println("Function ended")
}

func main() {
fun()
}

▶️Что ж, для этих целей как раз и используется пакет context.
С помощью context код выше можно переписать так:

package main

import (
"context"
"fmt"
"sync"
"time"
)

func main() {
timeLimit := time.Second * 10
ctx, cancel := context.WithTimeout(context.Background(), timeLimit)
defer cancel()
fun(ctx)
}

func isDone(ctx context.Context) bool {
select {
case <-ctx.Done():
return true
default:
return false
}
}

func FibonacciRecursion(ctx context.Context, n int) int {
if n <= 1 || isDone(ctx) {
return n
}
return FibonacciRecursion(ctx, n-1) + FibonacciRecursion(ctx, n-2)
}

func f(ctx context.Context, i int, wg *sync.WaitGroup) {
defer wg.Done()
fmt.Println(FibonacciRecursion(ctx, 45+i))
}

func fun(ctx context.Context) {
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go f(ctx, i, &wg)
}
wg.Wait()
println("Function ended")
}
Такие вот дела

1 минута