0

有没有办法保护业务逻辑的执行免受上下文取消?这是代码片段,可以更好地理解我的问题

func main() {
    ctx, cancel := context.WithCancel(context.Background())
    go foo(ctx)
    time.Sleep(time.Second * 3)
    cancel()
}

func foo(ctx context.Context) {
    // batch process data
    // context cancel should not stop function execution 
    // in the middle of business logic
    for i:= 0; i<10; i++ {
        fmt.Println("START of business logic for ID:", i)
        fmt.Println("Critical component")
        fmt.Print("Saving changes to DB...")
        time.Sleep(time.Second * 1)
        fmt.Println("Done")
        fmt.Println("END of business logic for ID:", i)
    }
}

输出:

START of business logic for ID: 0
Critical component
Saving changes to DB...Done
END of business logic for ID: 0
START of business logic for ID: 1
Critical component
Saving changes to DB...Done
END of business logic for ID: 1
START of business logic for ID: 2
Critical component
Saving changes to DB...Done
END of business logic for ID: 2

当执行在 for 循环中开始时,它不应该停止,直到它完成该迭代。这可以使用上下文取消吗?或者我应该使用其他方法,请建议。

去游乐场链接

4

1 回答 1

2

上下文取消是任务的信号机制。它不能确保强制执行——这取决于任务。这允许任务在中止较大的操作之前完成关键的子任务。

因此,在您的理论示例中,任何关键子步骤都应该忽略取消 - 并且只有在它们完成后轮询上下文:

select {
    case <-ctx.Done():
        return ctx.Err() // we're cancelled, abort
    default:
}

编辑:适用于您的示例

for i := 0; i < 10; i++ {
    //
    // critical section
    //

    // ...

    select {
    case <-ctx.Done():
        return ctx.Err() // we're cancelled, abort
    default:
    }
}

https://play.golang.org/p/kZ39VEVyP4L

于 2021-08-08T20:52:00.157 回答