Complete GraphQL implementation in Go with schema definition, query execution, and validation.
Execute GraphQL queries, mutations, and subscriptions against a schema.
Do is the all-in-one function that parses, validates, and executes a GraphQL operation.
func Do(p Params) *Result
type Params struct {
// The GraphQL schema to validate and execute against.
Schema Schema
// A GraphQL language formatted string representing the requested operation.
RequestString string
// The value provided as the first argument to resolver functions on the top
// level type (e.g. the query object type).
RootObject map[string]interface{}
// A mapping of variable name to runtime value for all variables defined
// in the RequestString.
VariableValues map[string]interface{}
// The name of the operation to use if RequestString contains multiple
// possible operations. Can be omitted if only one operation is present.
OperationName string
// Context may be provided to pass application-specific per-request
// information to resolve functions.
Context context.Context
}type Result struct {
Data interface{} `json:"data"`
Errors []gqlerrors.FormattedError `json:"errors,omitempty"`
Extensions map[string]interface{} `json:"extensions,omitempty"`
}
func (r *Result) HasErrors() boolExample:
result := graphql.Do(graphql.Params{
Schema: schema,
RequestString: `query Hero($ep: Episode) { hero(episode: $ep) { name } }`,
VariableValues: map[string]interface{}{
"ep": "JEDI",
},
Context: ctx,
})
if result.HasErrors() {
log.Printf("errors: %v", result.Errors)
}Use Execute when you have already parsed the document (e.g., to cache the AST).
func Execute(p ExecuteParams) (result *Result)
type ExecuteParams struct {
Schema Schema
Root interface{}
AST *ast.Document
OperationName string
Args map[string]interface{} // variable values
Context context.Context
}Example:
doc, err := parser.Parse(parser.ParseParams{Source: querySource})
if err != nil {
// handle parse error
}
result := graphql.Execute(graphql.ExecuteParams{
Schema: schema,
AST: doc,
Root: rootValue,
Args: variableValues,
Context: ctx,
})Subscriptions return a channel that emits *Result values. Close the channel from inside the subscribe resolver to end the subscription.
func Subscribe(p Params) chan *ResultSubscribe uses the same Params as Do but performs the subscribe phase instead of execute. The subscription field resolver (Field.Subscribe) returns a channel that is iterated.
SubscribeParams is an alternative params struct (defined for future use; the current Subscribe function takes Params):
type SubscribeParams struct {
Schema Schema
RequestString string
RootValue interface{}
VariableValues map[string]interface{}
OperationName string
FieldResolver FieldResolveFn
FieldSubscriber FieldResolveFn
}func ExecuteSubscription(p ExecuteParams) chan *ResultExecuteSubscription is like Execute but for subscription operations. Does not support extensions.
Example:
// Define a subscription field
subscriptionType := graphql.NewObject(graphql.ObjectConfig{
Name: "Subscription",
Fields: graphql.Fields{
"messageAdded": &graphql.Field{
Type: messageType,
Subscribe: func(p graphql.ResolveParams) (interface{}, error) {
ch := make(chan interface{})
go func() {
for msg := range messageChannel {
ch <- msg
}
close(ch)
}()
return ch, nil
},
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
return p.Source, nil
},
},
},
})
// Execute subscription
c := graphql.Subscribe(graphql.Params{
Schema: schema,
RequestString: `subscription { messageAdded { id text } }`,
})
for result := range c {
// handle each result
fmt.Println(result.Data)
}type FieldResolveFn func(p ResolveParams) (interface{}, error)
type ResolveParams struct {
// Source is the source/parent value.
Source interface{}
// Args is a map of arguments for the current field.
Args map[string]interface{}
// Info contains information about the current execution state.
Info ResolveInfo
// Context is the per-request context value.
Context context.Context
}
type ResolveInfo struct {
FieldName string
FieldASTs []*ast.Field
Path *ResponsePath
ReturnType Output
ParentType Composite
Schema Schema
Fragments map[string]ast.Definition
RootValue interface{}
Operation ast.Definition
VariableValues map[string]interface{}
}If no Resolve function is specified, the default resolver is used:
func DefaultResolveFn(p ResolveParams) (interface{}, error)The default resolver:
Source implements the FieldResolver interface (has a Resolve(ResolveParams) method) and calls it.Source with the same name (case-insensitive) as the GraphQL field.type FieldResolver interface {
Resolve(p ResolveParams) (interface{}, error)
}type ResponsePath struct {
Prev *ResponsePath
Key interface{} // string for field names, int for list indices
}
func (p *ResponsePath) AsArray() []interface{}
func (p *ResponsePath) WithKey(key interface{}) *ResponsePathUsed for interface and union type resolution at the object level:
type IsTypeOfFn func(p IsTypeOfParams) bool
type IsTypeOfParams struct {
Value interface{}
Info ResolveInfo
Context context.Context
}Extensions add middleware-like hooks to schema execution.
type Extension interface {
// Init initializes the extension and returns a (possibly modified) context.
Init(context.Context, *Params) context.Context
// Name returns the extension name.
Name() string
// ParseDidStart is called before parsing begins.
ParseDidStart(context.Context) (context.Context, ParseFinishFunc)
// ValidationDidStart is called before validation begins.
ValidationDidStart(context.Context) (context.Context, ValidationFinishFunc)
// ExecutionDidStart is called before execution begins.
ExecutionDidStart(context.Context) (context.Context, ExecutionFinishFunc)
// ResolveFieldDidStart is called before each field is resolved.
ResolveFieldDidStart(context.Context, *ResolveInfo) (context.Context, ResolveFieldFinishFunc)
// HasResult returns true if the extension wants to add data to the result.
HasResult() bool
// GetResult returns extension data to merge into result.Extensions.
GetResult(context.Context) interface{}
}
type ParseFinishFunc func(error)
type ValidationFinishFunc func([]gqlerrors.FormattedError)
type ExecutionFinishFunc func(*Result)
type ResolveFieldFinishFunc func(interface{}, error)Add extensions to a schema:
schema.AddExtensions(myExtension)Or via SchemaConfig:
schema, _ := graphql.NewSchema(graphql.SchemaConfig{
Query: queryType,
Extensions: []graphql.Extension{myExtension},
})Resolvers return (interface{}, error). Any non-nil error becomes a FormattedError in Result.Errors. The field value in Result.Data is set to null for that field.
For partial results with errors (field-level errors), return a non-nil value along with a non-nil error; the error is appended to Result.Errors and the field value may still be included.
Located errors provide location information:
func NewLocatedError(err interface{}, nodes []ast.Node) *gqlerrors.Error
func NewLocatedErrorWithPath(err interface{}, nodes []ast.Node, path []interface{}) *gqlerrors.ErrorInstall with Tessl CLI
npx tessl i tessl/golang-github-com--graphql-go--graphql@0.8.0docs