面试题答案
一键面试控制请求生命周期与处理超时的实现
在Go中,context
包用于在多个goroutine之间传递截止时间、取消信号等,以控制请求的生命周期和处理超时。
- 关键代码示例:
package main
import (
"context"
"fmt"
"net/http"
"time"
)
// 模拟调用外部API的函数
func callExternalAPI(ctx context.Context) (string, error) {
// 模拟一个需要一定时间的操作
select {
case <-time.After(2 * time.Second):
return "data from external API", nil
case <-ctx.Done():
return "", ctx.Err()
}
}
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// 创建带有超时的context
ctx, cancel := context.WithTimeout(r.Context(), 1*time.Second)
defer cancel()
data, err := callExternalAPI(ctx)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
fmt.Fprintf(w, "Response: %s", data)
})
fmt.Println("Server is running on http://localhost:8080")
http.ListenAndServe(":8080", nil)
}
- 代码解释:
- 创建带超时的context:
ctx, cancel := context.WithTimeout(r.Context(), 1*time.Second)
这行代码基于传入的请求上下文r.Context()
创建了一个新的带有1秒超时的上下文ctx
,同时返回一个取消函数cancel
。在函数结束时,通过defer cancel()
调用取消函数,以确保在函数返回前释放相关资源。 - 模拟外部API调用:
在
callExternalAPI
函数中,使用select
语句监听两个通道。time.After(2 * time.Second)
模拟外部API调用需要2秒时间完成。ctx.Done()
通道用于监听上下文是否被取消(比如超时)。如果ctx.Done()
通道接收到信号,说明上下文已被取消,函数返回错误。 - 处理结果:
在
main
函数的HTTP处理函数中,调用callExternalAPI(ctx)
获取数据。如果调用过程中出现错误(如超时),则返回HTTP 500错误。否则,将获取到的数据返回给客户端。
- 创建带超时的context:
通过这种方式,context
实现了对请求生命周期的控制以及超时处理,确保在规定时间内完成操作或及时取消不必要的任务。