gqlgen is a Go library for building GraphQL servers without any fuss.
fastgql This fork adds fasthttp support to the latest version of gqlgen.
- gqlgen is based on a Schema first approach — You get to Define your API using the GraphQL Schema Definition Language.
- gqlgen prioritizes Type safety — You should never see
map[string]interface{}
here. - gqlgen enables Codegen — We generate the boring bits, so you can focus on building your app quickly.
Still not convinced enough to use gqlgen? Compare gqlgen with other Go graphql implementations
- To install gqlgen run the command
go get github.com/arsmn/fastgql
in your project directory. - You could initialize a new project using the recommended folder structure by running this command
go run github.com/arsmn/fastgql init
.
First work your way through the Getting Started tutorial.
If you can't find what your looking for, look at our examples for example usage of gqlgen, or visit godoc.
Don't forget to replace go run github.com/99designs/gqlgen
with go run github.com/arsmn/fastgql
when you are using doc commands!
package main
import (
"log"
"github.com/valyala/fasthttp"
"github.com/arsmn/fastgql"
"<Your go module>/gql"
"<Your go module>/generated"
"github.com/arsmn/fastgql/graphql/handler"
"github.com/arsmn/fastgql/graphql/playground"
)
func main() {
playground := playground.Handler("GraphQL playground", "/query")
gqlHandler := handler.NewDefaultServer(generated.NewExecutableSchema(gql.NewResolver())).Handler()
h := func(ctx *fasthttp.RequestCtx) {
switch string(ctx.Path()) {
case "/query":
gqlHandler(ctx)
case "/":
playground(ctx)
default:
ctx.Error("not found", fasthttp.StatusNotFound)
}
}
log.Fatal(fasthttp.ListenAndServe(":8080", h))
}
package main
import (
"log"
"github.com/gofiber/fiber/v2"
"github.com/arsmn/fastgql"
"<Your go module>/gql"
"<Your go module>/generated"
"github.com/arsmn/fastgql/graphql/handler"
"github.com/arsmn/fastgql/graphql/playground"
)
func main() {
app := fiber.New()
srv := handler.NewDefaultServer(generated.NewExecutableSchema(gql.NewResolver()))
gqlHandler := srv.Handler()
playground := playground.Handler("GraphQL playground", "/query")
app.All("/query", func(c *fiber.Ctx) error {
gqlHandler(c.Context())
return nil
})
app.All("/playground", func(c *fiber.Ctx) error {
playground(c.Context())
return nil
})
log.Fatal(app.Listen(":8080"))
}
You could find a more comprehensive guide to help you get started here.
We also have a couple of real-world examples that show how to GraphQL applications with gqlgen seamlessly,
You can see these examples here or visit godoc.
If you think you've found a bug, or something isn't behaving the way you think it should, please raise an issue on GitHub.
We welcome contributions, Read our Contribution Guidelines to learn more about contributing to gqlgen
When you have nested or recursive schema like this:
type User {
id: ID!
name: String!
friends: [User!]!
}
You need to tell gqlgen that it should only fetch friends if the user requested it. There are two ways to do this;
Write a custom model that omits the friends field:
type User struct {
ID int
Name string
}
And reference the model in gqlgen.yml
:
# gqlgen.yml
models:
User:
model: github.com/you/pkg/model.User # go import path to the User struct above
If you want to Keep using the generated model, mark the field as requiring a resolver explicitly in gqlgen.yml
like this:
# gqlgen.yml
models:
User:
fields:
friends:
resolver: true # force a resolver to be generated
After doing either of the above and running generate we will need to provide a resolver for friends:
func (r *userResolver) Friends(ctx context.Context, obj *User) ([]*User, error) {
// select * from user where friendid = obj.ID
return friends, nil
}
Yes! You can by remapping it in config as seen below:
models:
ID: # The GraphQL type ID is backed by
model:
- github.com/arsmn/fastgql/graphql.IntID # An go integer
- github.com/arsmn/fastgql/graphql.ID # or a go string
This means gqlgen will be able to automatically bind to strings or ints for models you have written yourself, but the first model in this list is used as the default type and it will always be used when:
- Generating models based on schema
- As arguments in resolvers
There isn't any way around this, gqlgen has no way to know what you want in a given context.