SECRET OF CSS

Building a GraphQL Server Using the Schema-First Approach in Golang | by Logesh | Sep, 2022


Exploring the Golang GraphQL server with CRUD operations

0*DXWIpwA2O4XVXqIh 300w
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.

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.

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

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
1*COKFFtM XkfS kbW6SdAYQ
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.

1*LjDkXhUsw0c5dy L0raIVA
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

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:

1*xdG2jgaBys4a1vv 7UQdXQ
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.

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.

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:

Now that we’re good with our implementations, let’s move on to 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.

1*EYrzVHEclh1CFNSpzIZtlQ
go run server.go

Mutation AddBook

1*9kywll2kIKOCUnJclk3mXg

Query Book

1*7RNJGJmfwPZQYYi5e4GWnQ

Mutation UpdateBook

1*b0j85mmy0BQkcAXcZK6h6A

Query Books

1*zHfdvLjK4i5S3Oli IditQ

Query GetBooks

1*X loeM1W8WGo6ZVrpX MOg

Mutation DeleteBook

We could use any GraphQL client to access this service.

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.



News Credit

%d bloggers like this: