面试题答案
一键面试Context在Go语言实际编程场景中的主要用途
- 控制请求生命周期:在处理请求时,通过Context可以在不同的函数调用层级间传递请求的取消信号。当客户端关闭连接或者超时等情况发生时,上层函数可以通过取消Context来通知下层函数及时清理资源并返回,避免不必要的计算和资源占用。
- 传递请求范围数据:Context可以携带一些与请求相关的数据,如认证信息、请求ID等,方便在整个请求处理的链条中各个函数都能访问到这些数据,而不需要通过层层传递参数的方式。
- 设置截止时间:可以为一个操作设置截止时间,当超过这个时间后,操作自动取消,避免长时间阻塞。
在HTTP服务器处理函数中使用Context控制请求生命周期示例
package main
import (
"context"
"fmt"
"net/http"
"time"
)
func handler(w http.ResponseWriter, r *http.Request) {
// 获取请求的上下文
ctx := r.Context()
// 创建带有取消功能的上下文
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
// 模拟一个可能长时间运行的任务
done := make(chan struct{})
go func() {
time.Sleep(10 * time.Second)
close(done)
}()
select {
case <-ctx.Done():
// 如果上下文取消,说明请求超时或被取消
fmt.Fprintf(w, "Request cancelled or timed out: %v\n", ctx.Err())
return
case <-done:
// 如果任务正常完成
fmt.Fprintf(w, "Request completed successfully\n")
}
}
func main() {
http.HandleFunc("/", handler)
fmt.Println("Server listening on :8080")
http.ListenAndServe(":8080", nil)
}
在上述代码中:
- 首先通过
r.Context()
获取请求的上下文。 - 然后使用
context.WithTimeout
创建一个带有5秒超时的新上下文,并通过defer cancel()
确保在函数结束时取消这个上下文,释放相关资源。 - 模拟一个10秒的长时间运行任务,通过
select
语句监听上下文取消信号ctx.Done()
和任务完成信号done
。如果上下文先取消,说明请求超时或被取消,返回相应提示;如果任务先完成,则返回成功提示。