英文:
GqlGen - Accessing query input params in field resolver
问题
使用GqlGen生成代码后,创建了一些字段解析器方法。我需要在字段解析器中访问查询输入参数,但我不确定如何访问它。
我需要从上下文中获取这些值吗?还是还有其他方法?
查询解析器:
func (r *queryResolver) Main(ctx context.Context, device string) (*models.Main, error) {
...
}
字段解析器:
// Version是version字段的解析器。
func (r *mainResolver) Version(ctx context.Context, obj *models.Main) (*models.Version, error) {
// 我需要在这里访问传递给Main方法的device参数
panic(fmt.Errorf("not implemented: Version - version"))
}
谢谢,
英文:
After generating the code using GqlGen there are some field resolvers method that has been created. I need to access the query input param in the field resolver but I'm not sure how to access it.
Do I need to get these values from context? Or is there any other way?
Query Resolver:
func (r *queryResolver) Main(ctx context.Context, device string) (*models.Main, error) {
...
}
Field Resolver:
// Version is the resolver for the version field.
func (r *mainResolver) Version(ctx context.Context, obj *models.Main) (*models.Version, error) {
// I NEED TO ACCESS device param here which is passed in Main method
panic(fmt.Errorf("not implemented: Version - version"))
}
Thanks,
答案1
得分: 2
我认为你可以在父解析器的FieldContext
中找到参数。你可以使用graphql.GetFieldContext
来获取它,就像这样:
// Version是version字段的解析器。
func (r *mainResolver) Version(ctx context.Context, obj *models.Main) (*models.Version, error) {
device := graphql.GetFieldContext(ctx).Parent.Args["device"].(string)
// ...
}
Args
字段是一个map[string]interface{}
,所以你可以通过名称访问参数,然后将它们断言为它们应该是的类型。
如果解析器嵌套了多个级别,你可以编写一个函数,沿着上下文链向上查找,直到找到具有该值的祖先。使用Go 1.18+的泛型,该函数可以重用于任何值类型,使用类似于json.Unmarshal的模式:
func FindGqlArgument[T any](ctx context.Context, key string, dst *T) {
if dst == nil {
panic("nil destination value")
}
for fc := graphql.GetFieldContext(ctx); fc != nil; fc = fc.Parent {
v, ok := fc.Args[key]
if ok {
*dst = v.(T)
}
}
// 可选择在此处处理失败状态
}
并在代码中使用它:
func (r *deeplyNestedResolver) Version(ctx context.Context, obj *models.Main) (*models.Version, error) {
var device string
FindGqlArgument(ctx, "device", &device)
}
如果这不起作用,还可以尝试使用graphql.GetOperationContext
,这个函数基本上没有文档...(感谢@Shashank Sachan)
graphql.GetOperationContext(ctx).Variables["device"].(string)
英文:
I think you can find the arguments in the FieldContext
of the parent resolver. You can get it with graphql.GetFieldContext
like this:
// Version is the resolver for the version field.
func (r *mainResolver) Version(ctx context.Context, obj *models.Main) (*models.Version, error) {
device := graphql.GetFieldContext(ctx).Parent.Args["device"].(string)
// ...
}
The field Args
is a map[string]interface{}
, so you access the arguments by name and then type-assert them to what they're supposed to be.
If the resolver is nested several levels, you can write a function that walks up the context chain until it finds the ancestor that has the value. With Go 1.18+ generics, the function can be reused for any value type, using a pattern similar to json.Unmarshal:
func FindGqlArgument[T any](ctx context.Context, key string, dst *T) {
if dst == nil {
panic("nil destination value")
}
for fc := graphql.GetFieldContext(ctx); fc != nil; fc = fc.Parent {
v, ok := fc.Args[key]
if ok {
*dst = v.(T)
}
}
// optionally handle failure state here
}
And use it as:
func (r *deeplyNestedResolver) Version(ctx context.Context, obj *models.Main) (*models.Version, error) {
var device string
FindGqlArgument(ctx, "device", &device)
}
If that doesn't work, try also with graphql.GetOperationContext
, which is basically undocumented... (credit to @Shashank Sachan)
graphql.GetOperationContext(ctx).Variables["device"].(string)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论