面试题答案
一键面试防止上下文泄漏的方法
- 正确管理goroutine生命周期:确保启动的goroutine能够及时结束,避免在上下文取消后仍在运行。每个启动的goroutine都应该监听上下文的取消信号。
- 使用WithCancel、WithTimeout或WithDeadline创建上下文:根据业务需求选择合适的上下文创建函数。例如,使用
WithTimeout
设置一个明确的超时时间,这样即使业务逻辑没有主动取消,时间一到也会自动取消上下文。 - 在函数返回前清理资源:如果函数中使用了需要清理的资源(如数据库连接、文件句柄等),在函数返回前要确保这些资源被正确关闭或释放,即使上下文被取消。
实际代码示例
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
go func(ctx context.Context) {
select {
case <-time.After(3 * time.Second):
fmt.Println("operation completed")
case <-ctx.Done():
fmt.Println("operation cancelled due to timeout")
}
}(ctx)
time.Sleep(3 * time.Second)
}
在上述代码中:
- 使用
context.WithTimeout
创建了一个带有2秒超时的上下文ctx
,同时返回取消函数cancel
,并通过defer cancel()
确保在函数结束时取消上下文,防止潜在的泄漏。 - 在goroutine中,通过
select
语句监听ctx.Done()
通道,当上下文被取消(这里是超时导致取消)时,会打印相应的提示信息,及时结束goroutine,避免泄漏。