应使用gqlgen而非graphql-go:它在编译期校验resolver接口,避免runtime panic;需正确配置go module、手动执行generate命令、严格匹配函数签名,并用gqlerror.errorf处理错误。

别用 graphql-go 手写 schema,直接上 gqlgen——它生成的 resolver 接口在编译期就校验字段、类型、参数顺序和 context.Context 位置,而 graphql-go 的 runtime 反射匹配一出错就是 panic,且无法捕获 resolver 中的 context 超时或 cancel。
为什么 gqlgen init 卡住或报 module not found
本质是 Go module 环境没立住,不是 gqlgen 本身问题。
- 项目根目录必须已执行
go mod init example.com/myapp,且go.mod文件可读 - 运行
go env GOPROXY,若为空或返回direct,立刻设为https://goproxy.cn或https://proxy.golang.org - 绝对不要在
$GOPATH/src下初始化项目——gqlgen强制要求纯 module 模式,混用会路径解析失败 - 手动拉稳定版再试:
go get github.com/99designs/gqlgen@v0.17.49
schema.graphqls 改了但 resolver 不生效或编译报错
这是上线前最常踩的坑:gqlgen 不监听文件变更,改完不生成 = 白改。
- 每次保存
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是否在第一位,一个都不能错
Gin 路由注册后请求 404 或 panic
gqlgen 只生成 http.Handler,不启动 HTTP server,也不注册路由——这步必须手写,且路径、方法、封装方式全得对。
- 必须用
POST请求体传 JSON,Gin 路由要明确注册POST /graphql,不能只写GET - handler 必须用
graphql.NewDefaultServer包装 schema,不是直接gin.HandlerFunc调graphql.Do - Playground 页面(GraphiQL)路径需与 query 路径分离,比如
GET /playground返回 HTML,POST /graphql处理请求 - resolver 函数签名必须严格匹配生成接口:例如
func (r *queryResolver) Users(ctx context.Context, first *int) ([]*model.User, error),first是指针、返回值是[]*model.User,错一个 runtime 就 panic
真正容易被忽略的是 resolver 中错误处理方式:必须用 gqlerror.Errorf 包装错误,而不是 fmt.Errorf 或裸 return nil, err;否则客户端收不到标准 GraphQL 错误结构,只有空响应或 500。还有 context 透传——DB 查询、HTTP 调用、日志 trace 都得从 ctx 里取,不能靠全局变量或 RootValue 塞 map,那是 graphql-go 的老路子,gqlgen 要求显式传参。











