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

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

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

Начать курс

Введение: Почему GraphQL и Go — идеальная пара?

Современная веб-разработка требует гибких и производительных API. REST API, несмотря на свою популярность, часто страдает от перегрузки данных (over-fetching) или их нехватки (under-fetching). GraphQL решает эту проблему, позволяя клиенту запрашивать ровно то, что нужно. А Go (Golang) с его скоростью, простотой и встроенной поддержкой конкурентности становится идеальным языком для создания GraphQL-серверов.

В этом туториале мы шаг за шагом создадим полноценное GraphQL API на Go. Вы узнаете, как настроить сервер, определить схему, написать резолверы, а также реализовать запросы (queries) и мутации (mutations). К концу статьи у вас будет работающий API, готовый к интеграции с любым клиентом.

Шаг 1: Настройка проекта и установка зависимостей

Для начала создадим новый Go-модуль и установим необходимые библиотеки. Мы будем использовать две популярные GraphQL-библиотеки: graphql-go и graphql-go-handler.

1.1. Инициализация модуля

go mod init graphql-tutorial

1.2. Установка библиотек

go get github.com/graphql-go/graphql
go get github.com/graphql-go/handler

Эти библиотеки предоставляют все необходимые инструменты для работы со схемами, типами и резолверами.

Шаг 2: Создание базовой схемы GraphQL

Схема — это сердце GraphQL API. Она определяет, какие данные можно получить и какие действия выполнить. Начнём с простой модели "Пользователь".

2.1. Определение типа User

import "github.com/graphql-go/graphql"

var userType = graphql.NewObject(graphql.ObjectConfig{
    Name: "User",
    Fields: graphql.Fields{
        "id": &graphql.Field{
            Type: graphql.Int,
        },
        "name": &graphql.Field{
            Type: graphql.String,
        },
        "email": &graphql.Field{
            Type: graphql.String,
        },
    },
})

2.2. Создание корневого запроса

var rootQuery = graphql.NewObject(graphql.ObjectConfig{
    Name: "RootQuery",
    Fields: graphql.Fields{
        "user": &graphql.Field{
            Type: userType,
            Args: graphql.FieldConfigArgument{
                "id": &graphql.ArgumentConfig{
                    Type: graphql.Int,
                },
            },
            Resolve: func(p graphql.ResolveParams) (interface{}, error) {
                id, _ := p.Args["id"].(int)
                // Здесь будет логика получения пользователя из БД
                return getUserByID(id), nil
            },
        },
    },
})

2.3. Объединение в схему

var schema, _ = graphql.NewSchema(graphql.SchemaConfig{
    Query: rootQuery,
})

Шаг 3: Реализация резолверов и сервера

Теперь, когда схема готова, нужно написать резолверы — функции, которые фактически возвращают данные. Для простоты используем in-memory хранилище.

3.1. In-memory хранилище

type User struct {
    ID    int    `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

var users = []User{
    {ID: 1, Name: "Иван Петров", Email: "ivan@example.com"},
    {ID: 2, Name: "Мария Сидорова", Email: "maria@example.com"},
}

func getUserByID(id int) *User {
    for _, u := range users {
        if u.ID == id {
            return &u
        }
    }
    return nil
}

3.2. Запуск HTTP-сервера

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/graphql-go/handler"
)

func main() {
    h := handler.New(&handler.Config{
        Schema:   &schema,
        Pretty:   true,
        GraphiQL: true, // Включаем встроенную IDE
    })

    http.Handle("/graphql", h)
    fmt.Println("Сервер запущен на порту 8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

Теперь, запустив go run main.go, вы сможете открыть http://localhost:8080/graphql и протестировать API через GraphiQL.

Шаг 4: Добавление мутаций (Mutations)

Мутации позволяют изменять данные. Добавим возможность создавать новых пользователей.

4.1. Определение входного типа

var userInputType = graphql.NewInputObject(graphql.InputObjectConfig{
    Name: "UserInput",
    Fields: graphql.InputObjectConfigFieldMap{
        "name": &graphql.InputObjectFieldConfig{
            Type: graphql.NewNonNull(graphql.String),
        },
        "email": &graphql.InputObjectFieldConfig{
            Type: graphql.NewNonNull(graphql.String),
        },
    },
})

4.2. Создание корневой мутации

var rootMutation = graphql.NewObject(graphql.ObjectConfig{
    Name: "RootMutation",
    Fields: graphql.Fields{
        "createUser": &graphql.Field{
            Type: userType,
            Args: graphql.FieldConfigArgument{
                "input": &graphql.ArgumentConfig{
                    Type: graphql.NewNonNull(userInputType),
                },
            },
            Resolve: func(p graphql.ResolveParams) (interface{}, error) {
                input := p.Args["input"].(map[string]interface{})
                newUser := User{
                    ID:    len(users) + 1,
                    Name:  input["name"].(string),
                    Email: input["email"].(string),
                }
                users = append(users, newUser)
                return &newUser, nil
            },
        },
    },
})

4.3. Обновление схемы

var schema, _ = graphql.NewSchema(graphql.SchemaConfig{
    Query:    rootQuery,
    Mutation: rootMutation,
})

Теперь вы можете выполнять мутации через GraphiQL:

mutation {
  createUser(input: {name: "Алексей Иванов", email: "alex@example.com"}) {
    id
    name
    email
  }
}

Заключение: Что дальше?

Вы создали полноценное GraphQL API на Go! Этот туториал — лишь отправная точка. Вот что можно добавить для улучшения:

  • Подключение к реальной БД (PostgreSQL, MySQL) через GORM или sqlx.
  • Аутентификация с помощью JWT или

Блоги

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