GraphQL API с Go: пошаговый туториал для начинающих

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение в GraphQL и Go

GraphQL — это язык запросов для API, который позволяет клиентам получать именно те данные, которые им нужны, и ничего лишнего. В отличие от REST, где каждый эндпоинт возвращает фиксированную структуру данных, GraphQL даёт гибкость и контроль. В сочетании с Go (Golang) — быстрым, типобезопасным и простым языком — вы получаете мощный инструмент для создания современных веб-сервисов.

В этом туториале мы создадим простой GraphQL API на Go с нуля. Вы научитесь устанавливать зависимости, описывать схему, реализовывать резолверы и запускать сервер. Статья ориентирована на начинающих, поэтому все шаги подробно объяснены.

1. Подготовка проекта и установка зависимостей

Прежде чем писать код, убедитесь, что у вас установлен Go версии 1.18 или выше. Создайте новую директорию для проекта и инициализируйте модуль:

mkdir graphql-go-tutorial
cd graphql-go-tutorial
go mod init graphql-go-tutorial

Выбор библиотеки: gqlgen

Существует несколько библиотек для работы с GraphQL в Go. Мы будем использовать gqlgen — популярный генератор кода, который создаёт типы и резолверы на основе схемы. Установите его:

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

Инициализация gqlgen

Выполните команду для создания файлов по умолчанию:

go run github.com/99designs/gqlgen init

Эта команда создаст несколько файлов:

  • graph/schema.graphqls — файл схемы GraphQL;
  • graph/resolver.go — заготовка резолверов;
  • server.go — точка входа сервера;
  • gqlgen.yml — конфигурация генерации.

2. Описание схемы GraphQL

Откройте файл graph/schema.graphqls. По умолчанию там уже есть пример с типом Todo. Мы расширим его, добавив тип User и несколько запросов.

Замените содержимое файла на следующее:

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!
}

Здесь мы определили:

  • User — пользователь с полями id, name, email.
  • Todo — задача с полями id, text, done и ссылкой на пользователя.
  • Query — точки входа для чтения данных.
  • Mutation — операции для изменения данных.

3. Генерация кода и реализация резолверов

После описания схемы нужно сгенерировать Go-код. Выполните:

go run github.com/99designs/gqlgen generate

Это создаст файлы models_gen.go и обновит resolver.go. Теперь откройте graph/resolver.go.

Добавление хранилища данных

Для простоты будем хранить данные в памяти. Добавьте структуру в resolver.go:

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

Не забудьте импортировать пакет model.

Реализация запросов (Query)

Найдите сгенерированные методы для Query. Реализуем их:

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")
}

Реализация мутаций (Mutation)

Теперь добавим мутации. Они находятся в файле graph/schema.resolvers.go:

func (r *mutationResolver) CreateTodo(ctx context.Context, text string, userID string) (*model.Todo, error) {
    todo := &model.Todo{
        ID:   fmt.Sprintf("todo-%d", len(r.Resolver.Todos)+1),
        Text: text,
        Done: false,
        User: &model.User{ID: userID},
    }
    r.Resolver.Todos = append(r.Resolver.Todos, todo)
    return todo, nil
}

func (r *mutationResolver) MarkDone(ctx context.Context, id string) (*model.Todo, error) {
    for _, t := range r.Resolver.Todos {
        if t.ID == id {
            t.Done = true
            return t, nil
        }
    }
    return nil, fmt.Errorf("todo not found")
}

4. Запуск и тестирование API

Откройте server.go. В функции main замените инициализацию резолвера:

srv := handler.NewDefaultServer(graph.NewExecutableSchema(graph.Config{Resolvers: &graph.Resolver{
    Users: []*model.User{
        {ID: "user-1", Name: "Alice", Email: "alice@example.com"},
        {ID: "user-2", Name: "Bob", Email: "bob@example.com"},
    },
}}))

Запустите сервер:

go run server.go

Сервер будет доступен по адресу http://localhost:8080. Откройте браузер и перейдите по этому адресу — вы увидите встроенную GraphQL IDE (Playground).

Примеры запросов

В Playground выполните следующие запросы:

Получение всех пользователей:

query {
  users {
    id
    name
    email
  }
}

Создание задачи:

mutation {
  createTodo(text: "Изучить GraphQL", userId: "user-1") {
    id
    text
    done
  }
}

Получение задач

Блоги

Рекомендаций по книгам