面试题答案
一键面试使用边界
- WithTimeout:
- 边界:用于设置一个操作的最长执行时间。适用于子函数中发起网络请求或数据库查询时,限定这些操作不能无限制等待。例如,当调用数据库查询函数时,如果数据库出现异常长时间响应,WithTimeout 可以避免整个请求一直等待,而是在超时后快速返回,释放相关资源。
- 注意:超时时间的设置要根据实际业务场景合理调整。设置过短可能导致正常操作也被超时中断,设置过长则可能无法及时释放资源。
- WithCancel:
- 边界:适用于需要根据某些条件手动取消操作的场景。比如在子函数执行过程中,根据接收到的外部信号(如另一个 HTTP 请求通知),提前终止当前正在执行的网络请求或数据库查询等操作。
- 注意:要确保取消操作能正确传递到所有相关子函数,避免部分子函数继续执行不必要的操作。
正确传递context
- 顶层处理函数:
- 在 HTTP 处理函数入口处创建 context。例如,使用
context.WithTimeout
创建一个带有超时的 context:
func handler(w http.ResponseWriter, r *http.Request) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() // 调用子函数并传递 ctx err := subFunction1(ctx) if err!= nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } }
- 在 HTTP 处理函数入口处创建 context。例如,使用
- 子函数传递:
- 每个子函数都应该接受
context.Context
作为参数。例如:
func subFunction1(ctx context.Context) error { // 发起网络请求或数据库查询 req, err := http.NewRequestWithContext(ctx, "GET", "http://example.com", nil) if err!= nil { return err } resp, err := http.DefaultClient.Do(req) if err!= nil { return err } defer resp.Body.Close() // 处理响应 return nil }
- 这样,当顶层 context 取消(超时或手动取消)时,所有接受该 context 的子函数都能感知并及时取消正在进行的操作,如网络请求被取消,数据库查询被中断,从而确保资源的合理释放和请求的及时取消。
- 每个子函数都应该接受