Как я могу полностью прекратить запуск go func (), когда ctx истекает? - PullRequest
0 голосов
/ 25 сентября 2019

Когда я хочу ctx timeout, что я должен сделать, чтобы полностью завершить метод, выполняющий longRunningCalculation ()?

package main

import (
    "context"
    "log"
    "time"
)

func longRunningCalculation(timeCost int) chan string {
    result := make(chan string)
    go func() {
        time.Sleep(time.Second * (time.Duration(timeCost)))
        log.Println("Still doing other things...") //Even if it times out, this goroutine is still doing other tasks.
        result <- "Done"
        log.Println(timeCost)
    }()
    return result
}
func jobWithTimeout() {
    ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
    defer cancel()
    select {
    case <-ctx.Done():
        log.Println(ctx.Err())
        return
    case result := <-longRunningCalculation(3):
        log.Println(result)
    }
}

func main() {
    jobWithTimeout()
    time.Sleep(time.Second * 5)
}

Что вы ожидали увидеть?2019/09/25 11:00:16 превышен крайний срок контекста

Что вы видели вместо этого?2019/09/25 11:00:16 превышен крайний срок контекста 2019/09/25 11:00:17 Еще занимаюсь другими делами ...

1 Ответ

3 голосов
/ 25 сентября 2019

Чтобы остановить выполнение процедуры с помощью longRunningCalculation, когда истекает время ожидания контекста вызывающего, вам нужно передать ctx в longRunningCalculation и явно обработать тайм-аут контекста, так же, как в jobWithTimeout

Выполнение таких действий также означает вместо вызова time.Sleep, что time.Tick будет лучшим выбором, поэтому оба таймера работают одновременно.Вот так:

package main

import (
    "context"
    "log"
    "time"
)

func longRunningCalculation(ctx context.Context, timeCost int) chan string {
    result := make(chan string)
    go func() {
        calcDone := time.Tick(time.Second * time.Duration(timeCost))
        log.Printf("entering select (longRunningCalculation)")
        select {
        case <-ctx.Done():
            result <- "Caller timed out"
            return
        case <-calcDone:
            log.Println("Still doing other things...") //Even if it times out, this goroutine is still doing other tasks.
            result <- "Done"
        }
        log.Println(timeCost)
    }()
    return result
}

func jobWithTimeout() {
    ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
    defer cancel()
    result := longRunningCalculation(ctx, 3)
    log.Printf("entering select (jobWithTimeout)")
    select {
    case <-ctx.Done():
        log.Println(ctx.Err())
        return
    case res := <-result:
        log.Println(res)
    }
}

func main() {
    jobWithTimeout()
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...