防止上下文取消在业务逻辑中间停止函数执行
Prevent context cancel from stopping function execution in the middle of business logic
有没有办法保护业务逻辑的执行不受上下文取消的影响?这是代码片段,可以更好地理解我的问题
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 循环中开始时,它不应停止,直到完成该迭代。使用上下文取消可能吗?或者我应该使用其他方法,请建议。
上下文取消是任务的信号机制。它不能确保执行——这是留给任务的。这允许任务在中止较大的操作之前完成关键的子任务。
因此,在您的理论示例中,任何关键的子步骤都应忽略取消 - 只有在它们完成后才轮询上下文:
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:
}
}
有没有办法保护业务逻辑的执行不受上下文取消的影响?这是代码片段,可以更好地理解我的问题
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 循环中开始时,它不应停止,直到完成该迭代。使用上下文取消可能吗?或者我应该使用其他方法,请建议。
上下文取消是任务的信号机制。它不能确保执行——这是留给任务的。这允许任务在中止较大的操作之前完成关键的子任务。
因此,在您的理论示例中,任何关键的子步骤都应忽略取消 - 只有在它们完成后才轮询上下文:
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:
}
}