Using GraphQL in Golang
Tags: go, graphql, testing
Published: 2020-09-01 16:50:43

---
title: Using GraphQL in Golang
published: true
description: A simple multi-choice application will be used to demonstrate how GraphQL can be used in Golang with some test cases.
tags: #go #graphql #testing
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/4p042aoudvawg7zdbmik.jpg
---

### **Introduction**

From the official GraphQL documentation, 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.

I will be demonstrating with a simple application of how you start using GraphQL with Golang using the awesome [gqlgen](https://github.com/99designs/gqlgen) package

There are other packages used in Golang for GraphQL implementations, but these are the few reasons we use **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. You can get a complete read [here](https://gqlgen.com)

The purpose of this article is to give you a hands-on introduction to using Graphql in Golang. As such, we won't focus on definitions of terms in great detail.

We will be building a [multi-choice question and answer](https://github.com/victorsteven/multi-choice-graphql-go-app) application.

### **Basic Setup**

You can get the complete code for this article [here](https://github.com/victorsteven/multi-choice-graphql-go-app)

Create a folder of the project at any location on your computer(preferably where you have your Go projects), initialize go mod, then install the package gqlgen package.
```
mkdir multi-choice
cd multi-choice
go mod init multi-choice
go get github.com/99designs/gqlgen
```
Then create a **Makefile** to house all the commands that will be used.

```touch Makefile```

 Content:

```Makefile
init:
	go run github.com/99designs/gqlgen init
```
Initialize using: 
```
make init
```
After running the above command, the project structure will look like this(from the [documentation](https://gqlgen.com/getting-started)):

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/cmrajrxuknpksm1g8gq9.png)

The end product of the application we will be building has this structure:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/51o86t7z4ol7tjvwj0uy.png)


We will now customize to fit our use case.
The **gqlgen.yml** is modified to be:
{%gist https://gist.github.com/victorsteven/acfa3e6469215952562bc3cbbe0bf6e2 %}

### **Schemas**
A GraphQL schema is at the core of any GraphQL server implementation. It describes the functionality available to the client applications that connect to it. - [Tutorialspoint](https://www.tutorialspoint.com/graphql/graphql_schema.htm#:~:text=A%20GraphQL%20schema%20is%20at,build%20an%20interface%20around%20it.&text=Client%20applications%20can%20query%20the%20schema%20within%20its%20capabilities.)

gqlgen ships with a default schema.graphql. We can create more schemas based on project requirements.

The look of the schemas directory:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/6lhwfwy8hfjc2zx0lj3l.png)

I thought it neat to have the schema for a particular functionality to be in just one file(including the **mutation** and the **query**).
Rather than have a huge mutation/query that houses all mutation/query descriptions, we will have several, based on the number of concerns/features we are to implement.

In a nutshell:

- Base:
```graphql
type Mutation {
    #schema here
}

type Query {
    #schema here
}

```
- Extended:
```graphql
extend type Mutation {
    #schema here
} 

extend type Query {
    #schema here
}
```
The Question Schema:
{%gist https://gist.github.com/victorsteven/ef9e1d7dbb8a5ac6b819de2ffeae619b %}

The Question Option Schema:
{%gist https://gist.github.com/victorsteven/46e7138222920a6aae50317f53116122 %}
Observe there is no mutation/query. Well, question options are created only when questions are created, so they are not created independently.
The QuestionOptionInput was used as an argument in the Question schema defined above.

The Answer Schema:
{%gist https://gist.github.com/victorsteven/261db106288e5fd0e8dd64e00bee14d5 %}


Note:

Graphql does not permit more one definition of mutation/query. So we had to use the **extend** keyword when defining other mutation/query for other functionalities.
I don't consider it neat to have all mutation/query in one file as I have often seen from projects.

**Custom Types**

We can always add custom types outside the built-in types(ID, String, Boolean, Float, Int) to do so, we use the **scalar** keyword. 
A good example is Time(created_at, updated_at, etc)
That can be defined in the **schema.graphql** file:
{%gist https://gist.github.com/victorsteven/cb3c9c41d715359503bd9df0bc8e7bf2 %}

We don't need to bother adding the marshaling behavior to Go types; gqlgen has taken care of that. This also applies to other custom scalar types such as *Any*, *Upload*, and *Map*. Read more [here](https://gqlgen.com/reference/scalars). To add your own custom type, you will need to wire up the marshaling behavior to Go types.


### **Models**

Models' directory structure:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/cfywyazjxznaf56v4srn.png)

The graphql schema defined in the **schemas** directory is translated into Go code and saved in the **models.go** file.  
For example,

```graphql
type Question {
    id: ID!
    title: String!
    questionOption: [QuestionOption]
    createdAt: Time!
    updatedAt: Time!
}
```
Is translated to:
```go
type Question struct {
	ID             string            `json:"id"`
	Title          string            `json:"title"`
	QuestionOption []*QuestionOption `json:"questionOption"`
	CreatedAt      time.Time         `json:"createdAt"`
	UpdatedAt      time.Time         `json:"updatedAt"`
}
```
Where **QuestionOption** is a type just like **Question**

For us to translate schema to an actual Go code, we need to run a generate command.
Update the **Makefile**:
```Makefile
init:
	go run github.com/99designs/gqlgen init

generate:
	go run github.com/99designs/gqlgen

```

Then run the generate command:
```Makefile
make generate
```

This will generate the following in the models.go file
{%gist https://gist.github.com/victorsteven/0a774af8007dbc1a11d28c671b247957 %}

Observe that the **mutation** and **query** translations are not here. That will be in the **resolvers** as we will see later.

To have a different model for each schema, you can inform the gqlgen.yml about them. Read more [here](https://gqlgen.com/reference/resolvers) I think is neat to have the models inside the models.go file for now.

#### Custom hooks
You can define hooks to alter your model's behavior. In my case, I want the **id** to be a randomly generated string(UUID). So, to do that, I have to use [gorm's](https://gorm.io/docs/hooks.html) **BeforeCreate** hook:
{%gist https://gist.github.com/victorsteven/fbe747306a68375667f34661963a66f8 %}

#### Custom tags
We might need to add extra tags to our model structs. For instance, we might add a "db" tag, a "gorm" tag, a "bson" tag(when using MongoDB).

This is defined in the path: **models/model_tags**
{%gist https://gist.github.com/victorsteven/f5e5fe550107150f2076e21e22a5d3fd %}

We can update the generate command in the **Makefile** so that we always add the model tags each time we run the generate command.

```Makefile
generate:
	go run github.com/99designs/gqlgen && go run ./app/models/model_tags/model_tags.go
```

Running the generate command:
```
make generate
```

We will now have the **models.go** updated as:
{%gist https://gist.github.com/victorsteven/67d1edd06bb15cb32ce368474772a978 %}


### **Resolvers**

Structure:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/tghnxv1z7zoy6xu8l2lh.png)

A resolver acts as a GraphQL query handler
Mutations and Queries are translated into Go code and placed in the resolvers when the generate command is run:
```
make generate
```

So, for a mutation like this:

```graphql
type Mutation {
    CreateQuestion(question: QuestionInput!): QuestionResponse
}

```
The corresponding translation is:
```go
func (r *mutationResolver) CreateQuestion(ctx context.Context, question models.QuestionInput) (*models.QuestionResponse, error) {
   panic(fmt.Errorf("not implemented"))
}
```

- The article *slightly* adheres to DDD(Domain Driven Design) principles. So I thought it cool to have the **resolver.go** and all resolver related files to be placed in the *interfaces* directory.

The Question Resolver:
{%gist https://gist.github.com/victorsteven/b4e51c4bea12bb885abb74c483289832 %}

The Answer Resolver:
{%gist https://gist.github.com/victorsteven/d5a6eb03c69f333079e5d04af8eea24f %}

The above are simple crud operations. We use dependency injection to require external functionalities. The dependencies used are:

- QuestionService
- QuestionOptionService
- AnsService

which are defined in the base resolver file:
{%gist https://gist.github.com/victorsteven/84c5f1236eb92a288ffc998a25691e0a %}

This makes our resolver methods to be easily testable. We can easily replace those dependencies with fake ones, so we can achieve unit testing. Kindly check the test files.


### **Domain**
We injected some dependencies into our resolver above. Let's define those. This will be done in the domain:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/80n5qfux4a2dvz1mhr12.png)

The Question Repository:
{%gist https://gist.github.com/victorsteven/5390f2a15ada716188f4659e803e5532 %}

The Question Option Repository:
{%gist https://gist.github.com/victorsteven/7fb80b6ad3694b3460bb4b9c8da516f1 %}

The Answer Repository:
{%gist https://gist.github.com/victorsteven/2a2351c0574b16b09c33d783ac355e8e %}


### **Infrastructure**
We will now implement the interfaces defined above in the infrastructure layer:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/s46wkv4ioxqnutnixaot.png)

Implementing Question Methods:
{%gist https://gist.github.com/victorsteven/0081216488bed6e00777ff7af8bef6db %}

Implementing Question Option Methods:
{%gist https://gist.github.com/victorsteven/73ffd85356d774866a2fc5d6dce5365c %}

Implementing Answer Methods:
{%gist https://gist.github.com/victorsteven/97742742f770a5623d93bfa86249e4e7 %}

From the above implementations, **gorm** is used as the ORM to interacting with the PostgreSQL database.

Next, let's look at db.go file, which has functions that open the db and run migration.
{%gist https://gist.github.com/victorsteven/1c353386d30bc5efd5e688136263a1e3 %}

### **Running the Application**
We have pretty much everything wired. 
Let's now connect to the database, pass down the db instance.
All environmental variables are stored in a **.env** file at the root directory:
{%gist https://gist.github.com/victorsteven/4bd69527c3676727dcb9b817ff92b9e3 %}

In the root directory, create the **main.go** file. The content of the **server.go** that graphql initial setup ships with are added to the main.go file, and the file is deleted.

{%gist https://gist.github.com/victorsteven/ada8c116dcb17680097c1c9e4fdddb6e %}

We can update the **Makefile** that have the run and the test commands:

{%gist https://gist.github.com/victorsteven/682db8ba0ef6ed16b6f80c0ee588a988 %}

Run the application:
```
make run
```
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/mu84fvs4menxl0ug7pha.png)

#### **Trying Some Endpoints**

- Create a Question with multi-choice

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/wexk6xne1dfw4ru8xoui.png)

- Get one question with multi-choice

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/0dbpfu7nlet26ydehgo5.png)

- Answer the question:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/2b660jsyx936bmgcxzh5.png)



### **Running the tests**

- Integration Tests
You will need to create a test database and update the **.env** file with the credentials to run the integration tests in the infrastructure layer. 

- Unit Tests
The dependencies from the infrastructure layer are swapped with fake implementation. This allowed us to unit test the resolvers in the interfaces layer.

Having updated the **.env**, run all test cases from the root directory:
 ```
make test
```


### Conclusion
You have seen how simple it can be to start using graphql in golang. I hope you enjoyed the article. 
Get the complete code for this article [here](https://github.com/victorsteven/multi-choice-graphql-go-app)
I will be expanding on the current idea in future articles to add:
- File upload 
- Authentication

Stay tuned!

You can follow me on [twitter](https://twitter.com/stevensunflash) for any future announcement.

Thank you.