Go-Kit中Endpoint创建的上下文传递与执行机制技术问询
Go-Kit 代码实现与技术疑问解答
代码实现片段
1. 创建Get Endpoint
func MakeGetEndpoint(srv Service) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { _ = request.(getRequest) // we really just need the request, we don't use any value from it d, err := srv.Get(ctx) if err != nil { return getResponse{d, err.Error()}, nil } return getResponse{d, ""}, nil } }
2. 映射Endpoints
// mapping endpoints endpoints := napodate.Endpoints{ GetEndpoint: napodate.MakeGetEndpoint(srv) }
3. Endpoints的Get方法封装
func (e Endpoints) Get(ctx context.Context) (string, error) { req := getRequest{} resp, err := e.GetEndpoint(ctx, req) if err != nil { return "", err } getResp := resp.(getResponse) if getResp.Err != "" { return "", errors.New(getResp.Err) } return getResp.Date, nil }
技术疑问解答
疑问1:如何确保调用
e.GetEndpoint(ctx, req)时传入的ctx与MakeGetEndpoint中使用的ctx是同一个?
Go语言中context.Context是接口类型,参数传递时虽为值传递,但接口副本指向的底层上下文实例是同一个。你的代码里,调用e.GetEndpoint(ctx, req)传入的ctx会直接作为参数传递给MakeGetEndpoint返回的匿名函数,该匿名函数没有对ctx做任何修改或替换,直接将其传给srv.Get(ctx),因此二者必然是同一个上下文实例,无需额外操作即可保证一致性。疑问2:MakeGetEndpoint实际何时执行?它又是如何获取srv、ctx和request的?
- 执行时机:在执行
endpoints := napodate.Endpoints{GetEndpoint: napodate.MakeGetEndpoint(srv)}初始化Endpoints结构体时,MakeGetEndpoint会被调用,返回一个endpoint.Endpoint类型的匿名函数并赋值给GetEndpoint字段。 - 获取srv:srv是作为MakeGetEndpoint的入参直接传入的,借助Go的闭包特性,返回的匿名函数会捕获这个srv变量,后续调用匿名函数时可直接使用。
- 获取ctx和request:ctx和request是在调用
e.GetEndpoint(ctx, req)时,作为参数传递给MakeGetEndpoint返回的匿名函数的,匿名函数的参数列表明确声明了这两个参数,调用时直接传入即可。
- 执行时机:在执行
内容的提问来源于stack exchange,提问作者Lawliet
相关产品推荐
相关产品推荐

