A flexible and type-safe GraphQL schema builder for Go that automatically generates GraphQL schemas from Go types and functions. It nicely stands on the shoulders of github.com/graphql-go/graphql
, a battle-tested package widely used in production environments.
GraphQL in Go can be frustrating. If you've tried gqlgen
, you might have been overwhelmed by the code generation, hidden complexity, and unnecessary bloat. On the other hand, graphql-go/graphql
offers a more manual approach but comes with verbosity and an unintuitive structure that makes schema definition cumbersome. Gql is here to solve that problem by providing a flexible, type-safe, and intuitive way to build GraphQL schemas directly from Go types and functions—without code generation or unnecessary boilerplate.
- Type-Safe: Uses Go types to define your GraphQL schema effortlessly.
- Automatic Schema Generation: No need to manually define GraphQL types; just annotate your Go structs.
- Built on
graphql-go/graphql
: Leverages an established GraphQL implementation for Go. - Flexible and Extensible: Supports custom resolvers, input types, and mutations.
- Flexible Resolver Signature: Resolver methods can accept
context.Context
,graphql.ResolveInfo
, and input structs in any order and combination. - GQL Tags for Struct Fields: Uses struct tags to define GraphQL fields and arguments easily.
go get github.com/kadirpekel/gql
Here's a simple example of how to define and use a GraphQL schema with gql
:
package main
import (
"context"
"fmt"
"github.com/graphql-go/graphql"
"github.com/kadirpekel/gql"
)
// Struct fields are annotated with gql tags to define GraphQL schema
// The tag format is `gql:"fieldName[,modifier]"`
// Example: `gql:"ID,nonNull"` ensures the field is required in GraphQL
type User struct {
ID string `gql:"ID"`
FirstName string `gql:"firstName"`
LastName string `gql:"lastName"`
}
func (u *User) FullName() (string, error) {
return fmt.Sprintf("%s %s", u.FirstName, u.LastName), nil
}
type UserInput struct {
ID string `gql:"ID,nonNull"`
}
type query struct{}
func (q query) GetUser(ctx context.Context, args UserInput, info graphql.ResolveInfo) (*User, error) {
return &User{ID: args.ID, FirstName: "John", LastName: "Doe"}, nil
}
func (q query) ListUsers(info graphql.ResolveInfo) ([]*User, error) {
return []*User{
{ID: "1", FirstName: "John", LastName: "Doe"},
{ID: "2", FirstName: "Jane", LastName: "Doe"},
}, nil
}
func main() {
schema, err := gql.NewSchemaBuilder().
WithQuery(query{}).
BuildSchema()
if err != nil {
panic(err)
}
// Use the schema with your GraphQL server
}
The gql
struct tags define GraphQL schema properties directly on Go structs:
- Basic Mapping:
gql:"fieldName"
maps the Go struct field to a GraphQL field. - Modifiers: Add modifiers such as
nonNull
for required fields. - Example Usage:
type User struct {
ID string `gql:"ID,nonNull"` // Required GraphQL ID field
Name string `gql:"name"` // Maps to GraphQL "name" field
}
Resolvers in gql
are flexible and can accept parameters in any order:
context.Context
: Allows passing request-scoped values like authentication data.graphql.ResolveInfo
: Provides details about the query execution.- Input structs: Used for passing arguments to the resolver.
For example, all of the following resolver signatures are valid:
func (q query) GetUser(ctx context.Context, args UserInput) (*User, error) {}
func (q query) GetUser(info graphql.ResolveInfo, ctx context.Context, args UserInput) (*User, error) {}
func (q query) GetUser(args UserInput) (*User, error) {}
You can also define mutations using the same approach:
type mutation struct{}
func (m mutation) CreateUser(ctx context.Context, args User) (*User, error) {
return &User{ID: "3", FirstName: args.FirstName, LastName: args.LastName}, nil
}
Then include it in your schema:
schema, err := gql.NewSchemaBuilder().
WithQuery(query{}).
WithMutation(mutation{}).
BuildSchema()
To integrate with a GraphQL server, use github.com/graphql-go/handler
:
import (
"net/http"
"github.com/graphql-go/handler"
)
func main() {
schema, err := gql.NewSchemaBuilder().WithQuery(query{}).BuildSchema()
if err != nil {
panic(err)
}
h := handler.New(&handler.Config{
Schema: schema,
GraphiQL: true,
})
http.Handle("/graphql", h)
http.ListenAndServe(":8080", nil)
}
This project is licensed under the MIT License.