面试题答案
一键面试取消机制和超时机制的区别
-
触发条件
- 取消机制:由程序主动调用
CancelFunc
函数来触发。通常用于外部信号(如用户手动停止操作、服务器接收到关闭指令等)导致需要提前结束Goroutine
的情况。 - 超时机制:当设置的超时时间到达时自动触发。它是基于时间的一种结束条件,适用于希望
Goroutine
在一定时间内完成任务,如果超时则结束任务的场景。
- 取消机制:由程序主动调用
-
灵活性
- 取消机制:更加灵活,因为可以在程序的任何位置根据业务逻辑决定是否调用
CancelFunc
。这意味着可以在不同的条件下,如某个计算结果满足特定条件时,主动取消Goroutine
。 - 超时机制:相对固定,一旦设置了超时时间,只能等待时间到达后触发取消。虽然可以通过其他手段(如结合取消机制)提前结束,但本身基于时间的特性较为刚性。
- 取消机制:更加灵活,因为可以在程序的任何位置根据业务逻辑决定是否调用
-
使用场景
- 取消机制:常用于需要根据外部事件或业务逻辑决定是否结束
Goroutine
的场景,例如用户点击取消按钮、系统接收到关闭信号等。 - 超时机制:适用于对任务执行时间有明确限制的场景,比如网络请求、数据库查询等,避免长时间等待导致资源浪费或影响系统性能。
- 取消机制:常用于需要根据外部事件或业务逻辑决定是否结束
示例及业务场景选择
- 取消机制示例
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
go func(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("Goroutine is cancelled")
return
default:
fmt.Println("Goroutine is running")
time.Sleep(1 * time.Second)
}
}
}(ctx)
// 模拟外部事件,5秒后取消
time.Sleep(5 * time.Second)
cancel()
time.Sleep(1 * time.Second)
}
- 业务场景:在一个文件下载功能中,如果用户在下载过程中点击取消按钮,就可以调用
CancelFunc
来停止文件下载的Goroutine
,避免继续占用网络资源和系统资源。
- 超时机制示例
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
go func(ctx context.Context) {
select {
case <-ctx.Done():
fmt.Println("Goroutine is cancelled due to timeout")
return
default:
fmt.Println("Goroutine is running")
time.Sleep(5 * time.Second)
}
}(ctx)
time.Sleep(5 * time.Second)
}
- 业务场景:在一个调用第三方API的业务逻辑中,由于第三方API响应速度不确定,设置一个超时时间(如3秒)。如果3秒内API没有返回结果,就取消
Goroutine
,避免长时间等待,给用户返回错误提示,同时释放资源,避免影响系统其他功能的正常运行。
综上所述,在选择取消机制和超时机制时,应根据具体业务场景的需求来决定。如果需要根据外部事件或业务逻辑灵活结束Goroutine
,则选择取消机制;如果对任务执行时间有明确限制,为避免长时间等待导致资源浪费或影响系统性能,则选择超时机制。有时也可能需要将两者结合使用,以满足更复杂的业务需求。