Golang GraphQL – gqlgen

Graphql On Golang

GraphQL has been a buzzword for the better half of the past decade, and rightly so because of its advantages and simplicity. Combining it with a language like Go seems intuitive and I’ll tell you why.

What is GraphQL?

GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.

https://graphql.org/

It is like an interface between your database, client, and server. Developed by Facebook in 2012, it was released as Open Source in 2015. It is not a software implementation, but rather a specification – which means that it can be implemented by anyone and any language, and we as programmers are not confined to using something distributed by a company like Facebook.

To explain it simply, if you’ve ever used an API, you know how difficult it is to get exactly what you want – the names of all albums released in 2020 are quite easy to find. However, if we search for all the albums released by a certain studio, and casting a specific pair of actors in the last decade, we start getting into problems with the relational database. The traditional way to make queries through APIs used REST API as its interface. However, there were a few drawbacks:

Drawbacks to REST

  • If the data came from multiple sources across the organization, it becomes quite difficult to coherently define efficient processes and ensure that clients get the data they want.
  • In REST API, there was a big problem of over fetching – which meant we would typically gather the data by accessing multiple endpoints. Each endpoint, even though it may contain only ONE section of the data needed would provide additional unnecessary information.
  • REST APIs were slow – each change on the client query took a significant amount of time on the server due to its dependencies on the backend.

GraphQL was developed to cope with the need for more flexibility and efficiency! It solves many of the shortcomings and difficulties that developers experienced when interacting with REST APIs.

gqlgen

Finally, we are caught up with the basics, so I would like to introduce you to gqlgen, a graphql implementation on the Go language. Why gqlgen? Because it has more functionality than other Go implementations of graphql. Yes, there are more.

The company who bought gqlgen has benchmarked the performance and functionality of each implementation here.

gqlgen is a Go library for building GraphQL servers without any fuss. They employ a schema based approach where we need to only define the schema, and the rest of the server backend will be generated automatically by them.

Based on the graphql-go implementation which had a better type system, the dev team for gqlgen made incremental improvements:

  • Instead of runtime checks to check for proper implementation, they generated interfaces for the resolvers and the compiler could check that everything was implemented correctly.
  • They automated the writing of mapper code after generating type safe resolver interfaces. These combined ensures that the type specified by the client in their query is the same as the schema for the server and database.

There have been 1900 commits from 140 contributors on the gqlgen github repository. So if you face any problems you can contact the developers directly on this page.

Today, we are going to implement these things in our Google Colab notebook here.

Setup the project in a specific directory:

go run github.com/99designs/gqlgen init

This will auto generate the required files:

  • gqlgen.yml — The gqlgen config file
  • generated.go — The GraphQL execution runtime
  • models_gen.go — Generated models required to build the graph
  • resolver.go — This is where our application code lives
  • server/server.go — This is a minimal entry point that sets up an http.Handler to server
Gqlgen Folders Generated
Gqlgen Folders Generated

The file schema.graphqls will contain something similar to this, which is the basic schema for our server provided by gqlgen:

type Todo {
  id: ID!
  text: String!
  done: Boolean!
  user: User!
}

type User {
  id: ID!
  name: String!
}

type Query {
  todos: [Todo!]!
}

input NewTodo {
  text: String!
  userId: String!
}

type Mutation {
  createTodo(input: NewTodo!): Todo!
}

Next, check the file resolvers.go, which contains something like an error file. It compares the schema files with the models in ‘/graph/model/’ directory, and auto binds them. If there is any problems in binding, it will show up here in resolvers.go file:

Resolvers Go File
Resolvers Go File

As you can see, it says that two functions aren’t implemented. If there are more for you or others, then raise an issue on the gqlgen forums and someone will solve it for you. We’ll solve these quickly, after we add another function to resolvers that will track the server’s state:

type Resolver struct{
	todos []*model.Todo
}

We can now add the mutationResolver and queryResolver functions:

func (r *mutationResolver) CreateTodo(ctx context.Context, input model.NewTodo) (*model.Todo, error) {
	todo := &model.Todo{
		Text:   input.Text,
		ID:     fmt.Sprintf("T%d", rand.Int()),
		User: &model.User{ID: input.UserID, Name: "user " + input.UserID},
	}
	r.todos = append(r.todos, todo)
	return todo, nil
}

func (r *queryResolver) Todos(ctx context.Context) ([]*model.Todo, error) {
	return r.todos, nil
}

And well done ! You’ve just created your first gqlgen server.

Find your server at 127.0.0.1:8000 on your browser.

References