Building a GraphQL Server in Go

Table of Contents

  1. Introduction
  2. Prerequisites
  3. Setting Up
  4. Creating a GraphQL Schema
  5. Implementing Resolvers
  6. Handling Queries
  7. Handling Mutations
  8. Testing the GraphQL Server
  9. Conclusion

Introduction

In this tutorial, we will learn how to build a GraphQL server in Go. GraphQL is a query language for APIs that provides a more efficient and flexible alternative to traditional RESTful APIs. By the end of this tutorial, you will be able to create a fully functioning GraphQL server in Go.

Prerequisites

To follow this tutorial, you should have a basic understanding of Go programming language and have Go installed on your machine. You should also be familiar with the concepts of APIs and HTTP. Additionally, you should have a text editor or integrated development environment (IDE) set up for Go development.

Setting Up

First, let’s set up our Go project. Open your terminal or command prompt and create a new directory for your project:

mkdir graphql-server
cd graphql-server

Next, initialize a new Go module:

go mod init github.com/your-username/graphql-server

This will create a go.mod file in the current directory. Now, we can start building our GraphQL server.

Creating a GraphQL Schema

The first step in building a GraphQL server is to define a schema. The schema defines the structure of the data that the server can query and mutate. It also specifies the available operations and their arguments.

Create a new file called schema.graphql in the project directory and add the following code:

type Query {
  hello: String!
}

schema {
  query: Query
}

This schema defines a single query called hello, which returns a string. The exclamation mark after String indicates that the field is non-nullable.

Implementing Resolvers

Resolvers are responsible for executing the queries and mutations defined in the schema. They fetch the requested data and return the result to the client. Let’s create a new file called resolver.go and implement the resolver functions:

package main

type Resolver struct{}

func (r *Resolver) Hello() string {
  return "Hello, world!"
}

In this example, we created a struct called Resolver, which will serve as the root resolver for our GraphQL server. We implemented a method called Hello that returns the string “Hello, world!”.

Handling Queries

Now, let’s implement the code that handles queries. Create a new file called server.go and add the following code:

package main

import (
  "fmt"
  "github.com/graphql-go/graphql"
  "github.com/graphql-go/handler"
  "net/http"
)

func main() {
  schema, err := graphql.NewSchema(graphql.SchemaConfig{
    Query: graphql.NewObject(graphql.ObjectConfig{
      Name: "Query",
      Fields: graphql.Fields{
        "hello": &graphql.Field{
          Type: graphql.String,
          Resolve: func(p graphql.ResolveParams) (interface{}, error) {
            resolver := &Resolver{}
            return resolver.Hello(), nil
          },
        },
      },
    }),
  })
  
  if err != nil {
    fmt.Println("Error creating schema:", err)
    return
  }
  
  h := handler.New(&handler.Config{
    Schema:   &schema,
    Pretty:   true,
    GraphiQL: true,
  })
  
  http.Handle("/graphql", h)
  http.ListenAndServe(":8080", nil)
}

In this code, we create a new GraphQL schema with a single query field called hello. We provide a resolver function that creates an instance of our Resolver struct and calls its Hello method.

We then create an HTTP handler using the github.com/graphql-go/handler package, which handles incoming requests and serves the GraphQL API. Finally, we start a server that listens on port 8080 and handles requests using our GraphQL handler.

Handling Mutations

To demonstrate handling mutations, let’s add a new field called setMessage to our schema. This field will allow the client to set a custom message. Update the schema.graphql file with the following code:

type Mutation {
  setMessage(message: String!): String!
}

schema {
  query: Query
  mutation: Mutation
}

Next, update the server.go file with the following code:

// ...
schema, err := graphql.NewSchema(graphql.SchemaConfig{
  Query:    // ... (existing code)
  Mutation: graphql.NewObject(graphql.ObjectConfig{
    Name: "Mutation",
    Fields: graphql.Fields{
      "setMessage": &graphql.Field{
        Type: graphql.String,
        Args: graphql.FieldConfigArgument{
          "message": &graphql.ArgumentConfig{
            Type: graphql.NewNonNull(graphql.String),
          },
        },
        Resolve: func(p graphql.ResolveParams) (interface{}, error) {
          message, _ := p.Args["message"].(string)
          // Handle mutation logic here
          return message, nil
        },
      },
    },
  }),
})
// ...

In this code, we added a new mutation field called setMessage to the schema. We defined an argument called message of type String!, which is a non-null string.

We updated the resolver to handle the setMessage mutation. The Resolve function accesses the value of the message argument from the ResolveParams and returns it as the result.

Now, our GraphQL server is capable of handling both queries and mutations.

Testing the GraphQL Server

To test our GraphQL server, we can use the GraphiQL interface. Open your browser and navigate to http://localhost:8080/graphql. You should see the GraphiQL interface, where you can execute queries and mutations.

For example, to test the hello query, enter the following code in the GraphiQL editor and click the “Play” button:

query {
  hello
}

The server should respond with the following JSON:

{
  "data": {
    "hello": "Hello, world!"
  }
}

You can also test the setMessage mutation by entering the following code in the GraphiQL editor:

mutation {
  setMessage(message: "Hello, GraphQL!")
}

The server should respond with the following JSON:

{
  "data": {
    "setMessage": "Hello, GraphQL!"
  }
}

Congratulations! You have successfully built a GraphQL server in Go.

Conclusion

In this tutorial, we learned how to build a GraphQL server in Go. We started by creating a schema that defines the structure and operations of our API. We then implemented resolvers to handle queries and mutations. Finally, we tested the server using the GraphiQL interface.

By understanding and implementing GraphQL servers in Go, you can create powerful and efficient APIs that provide flexible data querying capabilities to your clients.