应直接使用gqlgen而非graphql-go/graphql手写方案:前者通过schema-first强制编译期校验resolver签名、字段映射与ctx传递,后者易漏指令支持与错误传播,调试成本高;gqlgen init卡住主因是module未初始化或goproxy失效,需执行go mod init、配置有效代理、避免gopath混用;schema修改后必须运行gqlgen generate并清理旧generated.go,否则resolver不生效或编译报错;resolver函数必须接收context.context、透传至db调用,并用gqlerror.errorf返回错误;http路由须满足post+json要求,用graphql/handler.newdefaultserver包装,playground路径须与query路径分离。

直接用 gqlgen,别碰 graphql-go/graphql 手写方案——前者编译期校验 resolver 签名、字段映射、context 传递,后者调试成本高、易漏指令支持和错误传播逻辑。
gqlgen init 卡住或报 module not found 怎么办
本质是 Go module 初始化不完整或代理不可用。
- 确认项目根目录已执行
go mod init example.com/myapp,且go.mod存在可读 - 运行
go env GOPROXY,若为空或返回direct,设为https://goproxy.cn或https://proxy.golang.org - 避免在
$GOPATH/src下初始化——gqlgen要求纯 module 模式,混用GOPATH会导致路径解析失败 - 手动拉取稳定版再试:
go get github.com/99designs/gqlgen@v0.17.49
schema 修改后 resolver 不生效或编译报错
gqlgen generate 没跑,或生成代码没对齐。
- 每次改完
schema.graphqls,必须手动运行go run github.com/99designs/gqlgen generate - 删掉旧的
graph/generated/generated.go再生成,避免缓存干扰 - 检查
gqlgen.yml的models配置是否覆盖了新增类型(如CreateUserInput),漏配会导致整条链路跳过 - 生成后看
graph/generated/generated.go里接口定义,确认你写的*queryResolver真实实现了它——比如方法名大小写、参数顺序、ctx context.Context是否在第一位
resolver 里怎么传 context 和处理错误
忽略 ctx 或直返 fmt.Errorf 是最常见两个坑。
- 所有 resolver 方法签名必须是
func(ctx context.Context, ...args) (T, error),少ctx参数会编译失败 - 数据库调用务必透传
ctx:如db.QueryRowContext(ctx, ...)或tx.ExecContext(ctx, ...) - 错误不能
return nil, fmt.Errorf("xxx"),前端只收"internal server error";要用gqlerror.Errorf("user not found: %v", id),并可加.Extensions附带业务码 -
gqlgen不保存ctx到Resolver结构体字段里,每次调用都是新ctx,别试图缓存它
HTTP 路由注册为什么总返回空或 400
没满足 GraphQL 对 HTTP 协议的硬性要求。
- GraphQL 只接受
POST /query(路径可自定义)+Content-Type: application/json,GET 查询字符串会被忽略 - 必须用
graphql/handler.NewDefaultServer包装,而不是手拼http.HandleFunc+graphql.Do——后者绕过中间件链,且不处理Variables解析 - Playground 调试页要单独挂载,路径不能和 query 路径相同:
http.Handle("/", playground.Handler("GraphQL", "/query"))和http.Handle("/query", srv)必须分开 - 用 Gin/Echo 时,别
c.ShouldBindJSON,直接传c.Request给srv.ServeHTTP,否则context丢失
最易被忽略的是:resolver 方法签名与生成接口的字段名、参数顺序、ctx 位置必须一字不差;gqlgen.yml 里 models 映射漏一项,生成的 struct 就是空的,查库时 panic;错误不用 gqlerror 包装,前端永远看不到具体信息。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











