使用gqlgen构建GraphQL API时嵌套Balance实体未解析的问题排查
gqlgen中User嵌套Balance字段Resolver未被调用、返回null的解决方法
问题根源
- Resolver职责混淆:你当前实现的
GetBalance是顶层Query字段的Resolver,仅在直接调用getBalance(id:...)查询时才会触发。而User类型下的balance属于对象嵌套字段,需要单独实现UserResolver接口的对应方法,gqlgen才会在解析User对象时自动调用它获取关联数据。 - SQL查询逻辑错误:
UserRepo.GetBalance使用Query处理单行查询,未调用rows.Next()就直接Scan,会导致数据读取失败,即使Resolver被触发也无法返回正确结果。
解决方案
1. 实现UserResolver的Balance字段Resolver
修改Resolver代码,新增UserResolver接口实现,专门处理User对象下的balance字段:
type Resolver struct { Repo *UserRepo } // 原有QueryResolver逻辑保留不变 func (r *queryResolver) GetUser(ctx context.Context, id int) (*model.User, error) { user := r.Repo.GetUser(int64(id)) log.Println("hello") return &model.User{ ID: int(user.Id), Firstname: user.Firstname, Lastname: user.Lastname, PhoneNumber: user.PhoneNumber, }, nil } func (r *queryResolver) GetBalance(ctx context.Context, id int) (*model.Balance, error) { balance := r.Repo.GetBalance(int64(id)) return &model.Balance{ ID: int(balance.Id), BalanceValue: balance.BalanceValue, }, nil } func (r *Resolver) Query() QueryResolver { return &queryResolver{r} } // 新增UserResolver相关代码 type userResolver struct{ *Resolver } func (r *Resolver) User() UserResolver { return &userResolver{r} } // Balance方法:专门处理User类型下的balance字段查询 func (r *userResolver) Balance(ctx context.Context, obj *model.User) (*model.Balance, error) { // 通过当前User的ID关联查询对应的balance balance := r.Repo.GetBalance(int64(obj.ID)) return &model.Balance{ ID: int(balance.Id), BalanceValue: balance.BalanceValue, }, nil } type queryResolver struct{ *Resolver } type mutationResolver struct { *Resolver }
2. 修复UserRepo的SQL查询逻辑
将Query替换为QueryRowContext(适合单行数据查询),并修正错误处理:
func (r *UserRepo) GetBalance(bid int64) *models.BalanceModel { balance := &models.BalanceModel{} query := `SELECT balance_id, balance_value FROM user_schema.balance WHERE user_id = $1` // 使用QueryRowContext处理单行查询,避免多行结果集的读取问题 err := constant.Db.QueryRowContext(context.Background(), query, bid).Scan(&balance.Id, &balance.BalanceValue) if err != nil { panic(err) } return balance }
3. 重新生成gqlgen代码
修改Resolver结构后,运行命令更新生成的代码,确保新的UserResolver接口被识别:
go run github.com/99designs/gqlgen generate
测试验证
再次发起你的查询请求:
query { getUser(id: 1) { firstname, lastname, balance { id, balanceValue } } }
此时gqlgen会在解析User对象时自动调用Balance方法,返回关联的balance数据,不再返回null。
内容的提问来源于stack exchange,提问作者Cross
相关产品推荐
相关产品推荐

