Introdução
GraphQL é uma linguagem de consulta moderna para APIs, desenvolvida pelo Facebook. Diferente do REST, ele permite que o cliente solicite apenas os dados necessários, reduzindo a carga na rede e acelerando o desenvolvimento. Neste tutorial, criaremos uma API GraphQL completa em Go (Golang) usando a biblioteca popular gqlgen. Você aprenderá como configurar o servidor, definir o schema, escrever resolvers e executar consultas. O artigo é voltado para desenvolvedores familiarizados com os fundamentos de Go, mas até iniciantes conseguirão seguir os passos graças aos comentários detalhados.
1. Configuração do projeto e instalação de dependências
Primeiramente, criaremos um novo projeto Go e instalaremos os pacotes necessários.
Passo 1: Inicialização do módulo
mkdir graphql-go-tutorial
cd graphql-go-tutorial
go mod init graphql-go-tutorial
Passo 2: Instalação do gqlgen
gqlgen é um gerador de código GraphQL para Go. Ele cria automaticamente resolvers com base no schema.
go get github.com/99designs/gqlgen@latest
Passo 3: Geração do esqueleto do projeto
Execute o comando de inicialização:
go run github.com/99designs/gqlgen init
Após a execução, você verá a estrutura:
graph/— pasta com o schema e resolversserver.go— ponto de entradagqlgen.yml— configuração do gerador
2. Definição do schema GraphQL
O schema descreve os tipos de dados e operações da API. Abra o arquivo graph/schema.graphqls e substitua seu conteúdo pelo seguinte:
type User {
id: ID!
name: String!
email: String!
age: Int!
}
type Query {
users: [User!]!
user(id: ID!): User
}
type Mutation {
createUser(name: String!, email: String!, age: Int!): User!
updateUser(id: ID!, name: String, email: String, age: Int): User
deleteUser(id: ID!): Boolean
}
Aqui definimos:
- User — objeto com campos id, name, email, age.
- Query — operações de leitura (obter todos os usuários ou um por ID).
- Mutation — operações de escrita (criar, atualizar, deletar).
Após salvar, execute a geração de código:
go run github.com/99designs/gqlgen generate
Isso criará os arquivos models_gen.go (tipos Go) e generated.go (interfaces dos resolvers).
3. Implementação dos resolvers e armazenamento de dados
Agora precisamos escrever a lógica para processar as consultas. Para simplificar, armazenaremos os dados em memória (slice de structs).
Passo 1: Criando o armazenamento
Crie o arquivo graph/store.go:
package graph
import "sync"
type Store struct {
mu sync.RWMutex
users []User
nextID int
}
func NewStore() *Store {
return &Store{
users: []User{
{ID: "1", Name: "Alice", Email: "alice@example.com", Age: 30},
{ID: "2", Name: "Bob", Email: "bob@example.com", Age: 25},
},
nextID: 3,
}
}
func (s *Store) GetUsers() []User {
s.mu.RLock()
defer s.mu.RUnlock()
return s.users
}
func (s *Store) GetUser(id string) *User {
s.mu.RLock()
defer s.mu.RUnlock()
for _, u := range s.users {
if u.ID == id {
return &u
}
}
return nil
}
func (s *Store) CreateUser(name, email string, age int) User {
s.mu.Lock()
defer s.mu.Unlock()
user := User{
ID: fmt.Sprintf("%d", s.nextID),
Name: name,
Email: email,
Age: age,
}
s.nextID++
s.users = append(s.users, user)
return user
}
func (s *Store) UpdateUser(id string, name, email *string, age *int) *User {
s.mu.Lock()
defer s.mu.Unlock()
for i, u := range s.users {
if u.ID == id {
if name != nil {
s.users[i].Name = *name
}
if email