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-tutorialChoosing 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@latestInitializing gqlgen
Run the command to create default files:
go run github.com/99designs/gqlgen initThis 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 generateThis 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
Read also
Working with WebAssembly and C++: Advanced Optimization and Integration Techniques
Chaos Engineering for Kotlin: Breaking the App to Save Production
Swift Application Security: Top 10 Vulnerabilities and Protection Methods
Cannot convert interface{} to string: how to tame generics in Go
Design Patterns in PHP with Examples: From A to Z