If you need to implement an API for your application, considering GraphQL (GQL) can be a game-changer. This article will guide you through the essentials of implementing a GraphQL server in Go and help you choose the right library for the job.

Why GraphQL?

Implementing GraphQL in Go

When deciding to use GraphQL as the API for your Go project, it's crucial to select a library that provides robust core functionality and speeds up development. Here are some popular libraries to consider:

gqlgen

graphql-go

graph-gophers/graphql-go

Choosing the Right Library

As an engineer, choosing the right library depends not only on technical specifications and product features but also on maintenance, community support, and the level of contribution/issues/PRs to the library. Here's my brief analysis based on these criteria:

Conclusion

Based on the criteria mentioned above, I chose gqlgen for my new project as an optimal option to consider. Its strong type safety, automatic resolver generation, and active community support made it a standout choice. Let's take a look at how to implement a simple GraphQL server with gqlgen.

Implementing a Simple GraphQL Server With gqlgen

Here's a step-by-step guide to setting up a basic GraphQL server using gqlgen:

  1. Install gqlgen:

    go get github.com/99designs/gqlgen@latest
    
  2. Initialize gqlgen in your project:

    gqlgen init
    
  3. Review and Configure gqlgen.yml:

    Make sure your gqlgen.yml file is properly configured to generate the necessary code. Here’s an example configuration:

schema:
  - schema.graphqls
exec:
  filename: generated/generated.go
model:
  filename: generated/models_gen.go
  package: generated
resolver:
  layout: follow-schema
  dir: graph
  package: graph
  1. Define your GraphQL schema (schema.graphqls):

    type Query {
      hello: String!
    }
    
    type Mutation {
      setMessage(message: String!): String!
    }
    
  2. Generate the GraphQL server code:

    gqlgen generate
    
  3. Implement the resolver (graph/resolver.go):

    package graph
    
    // This file will not be regenerated automatically.
    //
    // It serves as dependency injection for your app, add any dependencies you require here.
    
    type Resolver struct {
      Message string
    }
    
  4. Implement the resolvers (graph/schema.resolvers.go):

    package graph
    
    import (
      "context"
      "github.com/your_project/graph/generated"
    )
    
    func (r *Resolver) Query() generated.QueryResolver {
      return &queryResolver{r}
    }
    
    func (r *Resolver) Mutation() generated.MutationResolver {
      return &mutationResolver{r}
    }
    
    type queryResolver struct{ *Resolver }
    
    func (r *queryResolver) Hello(ctx context.Context) (string, error) {
      return r.Message, nil
    }
    
    type mutationResolver struct{ *Resolver }
    
    func (r *mutationResolver) SetMessage(ctx context.Context, message string) (string, error) {
      r.Message = message
      return r.Message, nil
    }
    
  5. Setup the server (server.go):

    package main
    
    import (
      "log"
      "net/http"
      "github.com/99designs/gqlgen/graphql/handler"
      "github.com/99designs/gqlgen/graphql/playground"
      "github.com/your_project/graph"
      "github.com/your_project/graph/generated"
    )
    
    const defaultPort = "8080"
    
    func main() {
      port := defaultPort
    
      srv := handler.NewDefaultServer(generated.NewExecutableSchema(generated.Config{Resolvers: &graph.Resolver{Message: "Hello, world!"}}))
    
      http.Handle("/", playground.Handler("GraphQL playground", "/query"))
      http.Handle("/query", srv)
    
      log.Printf("connect to http://localhost:%s/ for GraphQL playground", port)
      log.Fatal(http.ListenAndServe(":"+port, nil))
    }
    
  6. Run the server:

    go run server.go
    

Here’s the complete project structure:

your_project/
├── graph/
│   ├── resolver.go
│   └── schema.resolvers.go
├── generated/
│   ├── generated.go
│   └── models_gen.go
├── gqlgen.yml
├── schema.graphqls
└── server.go

By following these steps, you ensure that your gqlgen.yml configuration is properly set up before generating the GraphQL server code, aligning the entire setup process in a logical and correct order.