Better Programming

Advice for programmers.

Follow publication

Building a GraphQL Server Using the Schema-First Approach in Golang

Logesh
Better Programming
Published in
6 min readSep 13, 2022
Photo by Hossein Nasr on Unsplash

This is the Golang version of the article — Building GraphQL Server Using Schema-first Approach in Python.

It uses the exact same schema implementations in Golang.

The schema-first approach means we will write our schema first, using the GraphQL schema definition language. In the code-first approach, we will construct our schema using the library APIs.

We will be using gqlgen as our schema-first GraphQL library for Golang.

Overview of the Project

We are going to build the GraphQL server that handles the CRUD operation of Book in the Book Store.

Simply, we will be storing the book’s information in our database. To simplify this project, I haven’t used any kind of database; I just used an in-memory store and focused more on the GraphQL part.

Server Operations

  • Add books
  • Get book by ID
  • List books by genre
  • List all the books
  • Update the book
  • Delete the book

Building the GraphQL Server

Getting started

  • Let’s create our project dir.
  • Initialize the Go module with go mod init <dirname>.

gqlgen

  • Get our package by go get github.com/99designs/gqlgen
  • Initialize gqlgen by go run github.com/99designs/gqlgen init
  • run go mod tidy to get the required packages
Go module
gqlgen init

At this point, we could see various files and folders under the directory graphql. The directory graph was generated by gqlgen after we typed the init command.

Generate files

model/model_gen.go — this is a file with structs generated by gqlgen and defined by the schema file schema.graphqls

generated/generated.go — this is a file with generated code that injects context and middleware for each query and mutation.

You should not modify either of those files since they will be modified by gqlgen as we update our schema and generate.

graph/resolver.go — is the root graph resolver type. This file won’t get regenerated. This is the file where we declare our app’s dependencies, like our database.

schema.graphqls — is a GraphQL schema file that defines types, queries, and mutations. The schema file uses schema-definition-language (SDL) to describe data types and operations (queries/mutations) in a human-readable way.

schema.resolvers.go — is a Go file with wrapper code for queries and mutations defined in schema.graphqls

Defining our Schema

I invite you to define the schema and implement the code in your own way and requirement.

  • Delete the contents of the file graph/schema.graphqls (generated by gqlgen)
  • Delete the example code in schema.resolvers.go
  • Proceed to define our own schema in graph/schema.graphqls

I planned to have some GraphQL object types that can hold some information about the Books in our Book Store.

Here I have two Object types and one enum type to describe a Book.

Book type has the following fields:

  • title — String type and nonnullable
  • book_id — ID type
  • genre — enum type
  • author — array of Author types and non-nullable

Author type:

  • name — String type and non-nullable
  • mail — String type

BookGenre enum type:

  • has two values (FICTION, NONFICTION)

The above types are the basic types to handle the Books information.

Now we move forward to define the entry point for our GraphQL service.

Query type

I have the above Query type that has the following three fields:

  • book — get the book details by providing the book_id in the argument
  • books — get the list of available books
  • getbooks — get the list of books for the requested genre. The getgenre argument is an optional one. It has the default value of FICTION.
type GetBookResult{
isexists: Boolean!
book: Book
}

The GetBookResult type has two fields:

  • isexists — Boolean type and non-nullable. They tell whether the book information exists or not for the given book_id
  • book — Book type

Mutation type

Mutation type has three fields:

  • add_book — to create a book resource in our Book store by providing the inputs, and the response is the request's status.
  • update_book — updates the existing book information, and the response is the request's status.
  • delete_book — deletes the book with the given book id and returns the status of the operation.

The above types are used in the add_book field of the Mutation type.

The UpdateInput and the PutStatus types are used in the update_book field of the Mutation type.

type DeleteStatus{
iserror: Boolean!
description: String
}

DeleteStatus type is used in the delete_book field of the Mutation type.

We came to the end of our Schema definition.

generate

Once we are done with our schema, we need to generate gqlgen files using go run github.com/99designs/gqlgen generate. Here’s all the commands it creates:

missing go.sum entry and resolution

While running this command if you got some error like missing go.sum entry then get those packages to be added in go.sum. Mostly go get github.com/99designs/gqlgen this will resolve the error. then execute the generate command.

At this point, we have generated Go files for our schema. Proceed to implement our resolvers.

GraphQL Server Implementation

In-memory store

As I mentioned, I will use an in-memory data store (simply a variable) to store the book’s information.

Initializing our BOOKSTORE variable in resolver.go.

Let’s see the contents of the resolver.go file:

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{}

Now, let’s add our BOOKSTORE (list of Books) to the Resolver struct.

All set, except resolvers implementation.

Resolver Implementations

When we open the file, graph/schema.resolvers.go, we could see the initial boilerplate code generate by gqlgen generate command.

We have to modify our resolver methods to perform our requirements.

The methods to modify include the following:

  • AddBook
  • UpdateBook
  • DeleteBook
  • Book
  • Books
  • Getbooks

Basically everything!

AddBook

Before we implement our AddBook method, we need a logic to generate a unique Book ID.

Here is my implementation to find the next book id while adding a new book:

Now, here goes our AddBook’s method implementation:

addbook method implementation

UpdateBook

To update an existing book, do the following:

DeleteBook

To delete a book from the BOOKSTORE, here’s the code:

Book, Books, Getbooks

To get a book by ID, get a list of books by genre, or get all the books, here’s how to do it:

Full Resolver’s Code

Now that we’re good with our implementations, let’s move on to serving the clients.

Serving the Clients

Spin up the server by go run server.go.

server.go is the Go file which is generated while initializing the gqlgen project. This server.go will point our resolvers for the Query and the Mutations.

go run server.go

Mutation AddBook

Query Book

Mutation UpdateBook

Query Books

Query GetBooks

Mutation DeleteBook

We could use any GraphQL client to access this service.

Summary

In this article, we have seen how to build our own GraphQL server in Golang using gqlgen library(schema first approach).

You can find this project on my GitHub. Thanks for reading.

Logesh
Logesh

Written by Logesh

software_engineer@wireless_and_iot_domain

No responses yet

Write a response