Введение: Почему 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 или