Project Icon

graphql-go

完整支持GraphQL规范的Go语言服务器库

graphql-go是一个Go语言实现的GraphQL服务器库,支持2021年10月GraphQL规范。该库提供简洁API、并行解析器执行和订阅功能,兼容OpenTelemetry和OpenTracing标准。尽管仍在开发中,graphql-go已可用于生产环境。它采用方法集匹配实现灵活的解析器定义,并提供多种Schema配置选项,便于开发者构建GraphQL服务。

graphql-go Sourcegraph 构建状态 Go 报告 GoDoc

本项目的目标是通过一组惯用、易用的 Go 包来提供对2021年10月 GraphQL 规范的全面支持。

尽管仍在开发中(internal API 几乎肯定会发生变化),但该库已经可以安全地用于生产环境。

特性

  • 极简 API
  • 支持 context.Context
  • 支持 OpenTelemetryOpenTracing 标准
  • 对解析器进行模式类型检查
  • 基于方法集将解析器与模式匹配(可以使用 Go 接口或 Go 结构体解析 GraphQL 模式)
  • 处理解析器中的 panic
  • 并行执行解析器
  • 订阅
  • 字段上的指令访问器(API 可能在未来版本中发生变化)

(部分)文档 GoDoc

入门

要在本地运行一个简单的 GraphQL 服务器,请创建一个包含以下内容的 main.go 文件:

package main

import (
	"log"
	"net/http"

	graphql "github.com/graph-gophers/graphql-go"
	"github.com/graph-gophers/graphql-go/relay"
)

type query struct{}

func (query) Hello() string { return "Hello, world!" }

func main() {
	s := `
        type Query {
                hello: String!
        }
    `
	schema := graphql.MustParseSchema(s, &query{})
	http.Handle("/query", &relay.Handler{Schema: schema})
	log.Fatal(http.ListenAndServe(":8080", nil))
}

然后使用 go run main.go 运行该文件。测试方法如下:

curl -XPOST -d '{"query": "{ hello }"}' localhost:8080/query

有关更实际的用例,请查看我们的示例部分

解析器

解析器必须为其解析的 GraphQL 类型的每个字段拥有一个方法或字段。方法或字段名称必须是可导出的,并且与模式的字段名称不区分大小写匹配。 您可以通过使用 SchemaOpt: UseFieldResolvers() 来使用结构体字段作为解析器。例如:

opts := []graphql.SchemaOpt{graphql.UseFieldResolvers()}
schema := graphql.MustParseSchema(s, &query{}, opts...)

使用 UseFieldResolvers 模式选项时,结构体字段仅在以下情况下使用:

  • 结构体字段没有对应的方法
  • 结构体字段未实现接口方法
  • 结构体字段没有参数

该方法最多有两个参数:

  • 可选的 context.Context 参数。
  • 如果相应的 GraphQL 字段有参数,则必须有 *struct { ... } 参数。结构体字段的名称必须是可导出的,并且必须与 GraphQL 参数的名称不区分大小写匹配。

该方法最多有两个结果:

  • 由解析器确定的 GraphQL 字段的值。
  • 可选的 error 结果。

简单解析器方法的示例:

func (r *helloWorldResolver) Hello() string {
	return "Hello world!"
}

以下签名也是允许的:

func (r *helloWorldResolver) Hello(ctx context.Context) (string, error) {
	return "Hello world!", nil
}

不同操作的单独解析器

注意:此功能尚未在稳定版本中发布。要使用它,您需要运行 go get github.com/graph-gophers/graphql-go@master,在您的 go.mod 文件中将会出现类似以下内容:

v1.5.1-0.20230216224648-5aa631d05992

预计将在 v1.6.0 版本中发布。

GraphQL 规范允许在不同的查询类型中定义具有相同名称的字段。例如,以下是一个有效的模式定义:

schema {
  query: Query
  mutation: Mutation
}

type Query {
  hello: String!
}
type Mutation {
  hello: String!
}

如果我们使用单一的解析器结构体,上述模式会导致名称冲突,因为两种操作中的字段都对应根解析器(同一个Go结构体)中的方法。为了解决这个问题,该库允许使用根解析器的QueryMutationSubscription方法将查询、变更和订阅操作的解析器分开。这些特殊方法是可选的,如果定义了,它们会返回每个操作的解析器。例如,以下是对应上述模式定义的解析器。注意,在查询和变更定义中都有一个名为hello的字段:

type RootResolver struct{}
type QueryResolver struct{}
type MutationResolver struct{}

func(r *RootResolver) Query() *QueryResolver {
  return &QueryResolver{}
}

func(r *RootResolver) Mutation() *MutationResolver {
  return &MutationResolver{}
}

func (*QueryResolver) Hello() string {
	return "Hello query!"
}

func (*MutationResolver) Hello() string {
	return "Hello mutation!"
}

schema := graphql.MustParseSchema(sdl, &RootResolver{}, nil)
...

模式选项

  • UseStringDescriptions() 启用双引号和三引号的使用。未启用时,注释会被解析为描述。
  • UseFieldResolvers() 指定是否使用结构体字段解析器。
  • MaxDepth(n int) 指定查询中字段嵌套的最大深度。默认值为0,表示禁用最大深度检查。
  • MaxParallelism(n int) 指定每个请求允许并行运行的解析器最大数量。默认值为10。
  • Tracer(tracer trace.Tracer) 用于跟踪查询和字段。默认为noop.Tracer
  • Logger(logger log.Logger) 用于记录查询执行期间的恐慌。默认为exec.DefaultLogger
  • PanicHandler(panicHandler errors.PanicHandler) 用于在查询执行期间将恐慌转换为错误。默认为errors.DefaultPanicHandler
  • DisableIntrospection() 禁用内省查询。
  • DirectiveVisitors() 向模式添加指令访问者实现。参见examples/directives/authorization中的示例。

自定义错误

解析器返回的错误可以通过实现ResolverError接口来包含自定义扩展:

type ResolverError interface {
	error
	Extensions() map[string]interface{}
}

简单自定义错误的示例:

type droidNotFoundError struct {
	Code    string `json:"code"`
	Message string `json:"message"`
}

func (e droidNotFoundError) Error() string {
	return fmt.Sprintf("error [%s]: %s", e.Code, e.Message)
}

func (e droidNotFoundError) Extensions() map[string]interface{} {
	return map[string]interface{}{
		"code":    e.Code,
		"message": e.Message,
	}
}

这可能会产生如下GraphQL错误:

{
  "errors": [
    {
      "message": "error [NotFound]: This is not the droid you are looking for",
      "path": [
        "droid"
      ],
      "extensions": {
        "code": "NotFound",
        "message": "This is not the droid you are looking for"
      }
    }
  ],
  "data": null
}

跟踪

默认情况下,该库使用noop.Tracer。如果你想更改,可以分别使用OpenTelemetry或OpenTracing实现:

// OpenTelemetry跟踪器
package main

import (
	"github.com/graph-gophers/graphql-go"
	"github.com/graph-gophers/graphql-go/example/starwars"
	otelgraphql "github.com/graph-gophers/graphql-go/trace/otel"
	"github.com/graph-gophers/graphql-go/trace/tracer"
)
// ...
_, err := graphql.ParseSchema(starwars.Schema, nil, graphql.Tracer(otelgraphql.DefaultTracer()))
// ...

或者你可以传递一个现有的trace.Tracer实例:

tr := otel.Tracer("example")
_, err = graphql.ParseSchema(starwars.Schema, nil, graphql.Tracer(&otelgraphql.Tracer{Tracer: tr}))
// OpenTracing跟踪器
package main

import (
	"github.com/graph-gophers/graphql-go"
	"github.com/graph-gophers/graphql-go/example/starwars"
	"github.com/graph-gophers/graphql-go/trace/opentracing"
	"github.com/graph-gophers/graphql-go/trace/tracer"
)
// ...
_, err := graphql.ParseSchema(starwars.Schema, nil, graphql.Tracer(opentracing.Tracer{}))

// ...

如果你需要实现自定义跟踪器,该库会接受任何实现以下接口的跟踪器:

type Tracer interface {
    TraceQuery(ctx context.Context, queryString string, operationName string, variables map[string]interface{}, varTypes map[string]*introspection.Type) (context.Context, func([]*errors.QueryError))
    TraceField(ctx context.Context, label, typeName, fieldName string, trivial bool, args map[string]interface{}) (context.Context, func(*errors.QueryError))
    TraceValidation(context.Context) func([]*errors.QueryError)
}

示例

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

白日梦AI

白日梦AI提供专注于AI视频生成的多样化功能,包括文生视频、动态画面和形象生成等,帮助用户快速上手,创造专业级内容。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

讯飞绘镜

讯飞绘镜是一个支持从创意到完整视频创作的智能平台,用户可以快速生成视频素材并创作独特的音乐视频和故事。平台提供多样化的主题和精选作品,帮助用户探索创意灵感。

Project Cover

讯飞文书

讯飞文书依托讯飞星火大模型,为文书写作者提供从素材筹备到稿件撰写及审稿的全程支持。通过录音智记和以稿写稿等功能,满足事务性工作的高频需求,帮助撰稿人节省精力,提高效率,优化工作与生活。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号