面试题答案
一键面试- 实现超时和取消机制
- 创建带有超时或取消功能的Context:
在调用多个下游服务的入口处,使用
context.WithTimeout
或context.WithCancel
创建Context
。例如,使用context.WithTimeout
创建一个带有5秒超时的Context
:ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel()
- 传递Context到下游服务:
在调用每个下游服务时,将创建的
Context
作为参数传递进去。假设下游服务的函数签名如下:
调用时:func downstreamService(ctx context.Context) error { // 下游服务逻辑 }
err1 := downstreamService1(ctx) err2 := downstreamService2(ctx)
- 下游服务内部处理Context:
下游服务内部在执行可能耗时的操作前,要定期检查
Context
的状态。例如,在一个for
循环中处理任务时:func downstreamService(ctx context.Context) error { for { select { case <-ctx.Done(): // 处理取消或超时,释放资源 return ctx.Err() default: // 执行任务 } } return nil }
- 创建带有超时或取消功能的Context:
在调用多个下游服务的入口处,使用
- 处理错误关系
- 区分不同错误类型:
下游服务返回的错误可能是业务错误,而
Context
的错误是与超时或取消相关的。可以使用类型断言或自定义错误类型来区分。例如,定义一个业务错误类型:
在下游服务中返回业务错误:type BusinessError struct { Message string } func (be BusinessError) Error() string { return be.Message }
func downstreamService(ctx context.Context) error { if someBusinessCondition { return BusinessError{"业务错误信息"} } select { case <-ctx.Done(): return ctx.Err() default: // 正常执行 } return nil }
- 调用方处理错误:
在调用多个下游服务的地方,处理不同类型的错误。例如:
err1 := downstreamService1(ctx) if err1 != nil { if _, ok := err1.(BusinessError); ok { // 处理业务错误 } else if err1 == context.DeadlineExceeded || err1 == context.Canceled { // 处理超时或取消错误 } }
- 区分不同错误类型:
下游服务返回的错误可能是业务错误,而
这样可以确保在复杂的Go微服务架构中,优雅地实现超时和取消机制,并正确处理不同类型的错误。