GraphQL API with Go: Step-by-Step Tutorial for Beginners

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction to GraphQL and Go

GraphQL is a query language for APIs that allows clients to get exactly the data they need, and nothing extra. Unlike REST, where each endpoint returns a fixed data structure, GraphQL provides flexibility and control. Combined with Go (Golang) — a fast, type-safe, and simple language — you get a powerful tool for building modern web services.

In this tutorial, we will create a simple GraphQL API in Go from scratch. You will learn how to install dependencies, describe a schema, implement resolvers, and run a server. The article is aimed at beginners, so all steps are explained in detail.



1. Project Setup and Dependency Installation

Before writing code, make sure you have Go version 1.18 or higher installed. Create a new directory for the project and initialize the module:

mkdir graphql-go-tutorialcd graphql-go-tutorialgo mod init graphql-go-tutorial


Choosing a Library: gqlgen

There are several libraries for working with GraphQL in Go. We will use gqlgen — a popular code generator that creates types and resolvers based on a schema. Install it:

go get github.com/99designs/gqlgen@latest


Initializing gqlgen

Run the command to create default files:

go run github.com/99designs/gqlgen init

This command will create several files:

  • graph/schema.graphqls — GraphQL schema file;
  • graph/resolver.go — resolver stub;
  • server.go — server entry point;
  • gqlgen.yml — generation configuration.


2. Describing the GraphQL Schema

Open the file graph/schema.graphqls. By default, it already contains an example with the Todo type. We will extend it by adding the User type and several queries.

Replace the file contents with the following:

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

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

type Query { todos: [Todo!]! users: [User!]! user(id: ID!): User}

type Mutation { createTodo(text: String!, userId: ID!): Todo! markDone(id: ID!): Todo!}

Here we have defined:

  • User — a user with id, name, email fields.
  • Todo — a task with id, text, done fields and a reference to a user.
  • Query — entry points for reading data.
  • Mutation — operations for modifying data.


3. Code Generation and Resolver Implementation

After describing the schema, you need to generate Go code. Run:

go run github.com/99designs/gqlgen generate

This will create the models_gen.go file and update resolver.go. Now open graph/resolver.go.



Adding a Data Store

For simplicity, we will store data in memory. Add a structure to resolver.go:

type Resolver struct {    Users []*model.User    Todos []*model.Todo}

Don't forget to import the model package.



Implementing Queries

Find the generated methods for Query. Let's implement them:

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

func (r *queryResolver) Users(ctx context.Context) ([]*model.User, error) { return r.Resolver.Users, nil}

func (r *queryResolver) User(ctx context.Context, id string) (*model.User, error) { for _, u := range r.Resolver.Users { if u.ID == id { return u, nil } } return nil, fmt.Errorf("user not found")}

Blogs

Book Recommendations