直接用graphql-go/graphql的ParseQuery做纯语法校验最稳,它仅执行词法和语法分析,返回*ast.Document或error,不依赖schema,适合前置校验,能捕获括号不匹配、字段名缺引号等语法错误。

直接用 graphql-go/graphql 自带的解析器做校验最稳,不推荐手写正则或简易 AST 分析——GraphQL 查询字符串含嵌套、变量、指令、fragment 等语法糖,靠字符串匹配极易漏判。
用 graphql.ParseQuery 做纯语法校验
它只做词法+语法分析,不执行、不依赖 schema,适合前置校验。返回 *ast.Document 表示合法,error 表示非法(如括号不匹配、字段名缺引号、未闭合 fragment 等)。
-
graphql.ParseQuery输入是 raw string,输出是 AST 根节点或 error,零依赖、无副作用 - 它不检查字段是否存在、类型是否匹配——那是
Validate阶段的事,别混用 - 常见误判点:
{ user { name } }合法;{ user { name }(缺右大括号)报unexpected EOF;{ user(name:)}(参数值缺失)报expected value, found ) - 错误信息较底层,如需用户友好提示,可对特定 error message 做简单 switch 匹配,例如:
strings.Contains(err.Error(), "unexpected EOF")→ “查询语句不完整”
为什么不用 gqlgen 的 parser?
gqlgen 的 parser.ParseQuery 功能更全,但默认绑定 schema 类型系统,初始化成本高,且会尝试解析变量定义和 operation name——对轻量校验属于过度设计。
- 它要求传入
*ast.Source,还要处理parser.Options,调用链长 - 若 query 含未定义的 directive(如
@auth),gqlgenparser 默认报错;而graphql-go/graphql的ParseQuery默认忽略未知 directive(更宽松) - 除非你已引入
gqlgen且需要复用其 AST 结构做后续分析,否则没必要为校验单独拉这个依赖
校验器封装建议:避免 panic 和空指针
实际集成时,ParseQuery 返回的 *ast.Document 是非空指针,但它的 Operations 字段可能为 nil(比如只有 fragment 定义没 operation),别直接 deref。
立即学习“go语言免费学习笔记(深入)”;
- 始终先判断
err != nil,再处理doc - 若需确认至少有一个 operation,加一层
len(doc.Operations) == 0检查,而非假设doc.Operations[0] - 不要在 HTTP handler 中直接
log.Fatal或 panic 错误——应返回400 Bad Request+ 错误摘要 - 示例片段:
doc, err := graphql.ParseQuery(queryString)
if err != nil {
return fmt.Errorf("invalid GraphQL syntax: %w", err)
}
if len(doc.Operations) == 0 {
return errors.New("no operation found")
}
真正难的是区分「语法错」和「语义错」:少个括号是语法错,字段名拼错是语义错(得靠 schema 验证)。轻量校验器只管前者,后者交给后续 pipeline。


















