在GoFr框架中集成GraphQL API,优化Resolver适配HTTP Handler特性
针对GoFr集成GraphQL优化的解决方案
1. 让GraphQL Resolver适配HTTP Handler签名并访问Context
graph-gophers/graphql-go的Resolver本身不直接支持GoFr的Context,但可以通过自定义Resolver包装器实现Context传递:
- 在
graphql.go的ServeHTTP方法中,将GoFr的Context注入到GraphQL请求上下文(比如借助context.WithValue) - 编写包装函数,把自定义Resolver(兼容GoFr Context签名)转换成graphql-go要求的
FieldResolveFn,示例思路如下:// 自定义Resolver类型,直接接收GoFr Context type GofrResolver func(gofr.Context, map[string]interface{}) (interface{}, error) // 包装成graphql-go兼容的Resolver func WrapResolver(r GofrResolver) graphql.FieldResolveFn { return func(p graphql.ResolveParams) (interface{}, error) { // 从上下文提取GoFr Context ctx := p.Context.Value("gofr_ctx").(gofr.Context) return r(ctx, p.Args) } } - 注册Schema字段时用
WrapResolver包装自定义Resolver,就能让Resolver直接访问GoFr Context,顺利集成追踪、日志等能力
2. 规范访问Container资源的方式
可以通过依赖注入到Resolver结构体简化资源获取:
- 初始化Resolver时,从Container中取出数据库连接、服务实例等,直接注入到Resolver结构体属性中,避免在Resolver方法里重复调用
Container.Get - 示例实现:
type UserResolver struct { db *sql.DB authService *AuthService } func NewUserResolver(c gofr.Container) *UserResolver { return &UserResolver{ db: c.GetDB(), authService: c.GetService("auth").(*AuthService), } } // Resolver方法直接使用结构体中的资源 func (r *UserResolver) GetUser(ctx gofr.Context, args map[string]interface{}) (interface{}, error) { var user User err := r.db.QueryRowContext(ctx, "SELECT id, name FROM users WHERE id = ?", args["id"]).Scan(&user.ID, &user.Name) if err != nil { ctx.Logger.Error("查询用户失败", err) return nil, err } return user, nil } - 这种方式符合GoFr依赖注入规范,代码更简洁,也方便单元测试时模拟资源注入
内容的提问来源于stack exchange,提问作者Umang Mundhra
相关产品推荐
相关产品推荐

