Introdução: Por que GraphQL e Go são a combinação perfeita
\nNo desenvolvimento web moderno, o GraphQL se tornou um padrão para criar APIs flexíveis e eficientes. Combinado com a linguagem Go (Golang), conhecida por seu desempenho e simplicidade, você obtém uma ferramenta poderosa para o desenvolvimento backend. Neste tutorial passo a passo, criaremos uma API GraphQL completa em Go do zero, usando a biblioteca popular gqlgen.
Você aprenderá como configurar o projeto, definir o esquema, implementar resolvers e adicionar middleware para autenticação. Ao final do artigo, você terá uma API funcional, pronta para integração com qualquer frontend.
\n\n1. Configuração do projeto e instalação de dependências
\nPrimeiro, criaremos um novo módulo Go e instalaremos os pacotes necessários. Certifique-se de ter o Go versão 1.18 ou superior instalado.
\nmkdir graphql-go-tutorial\ncd graphql-go-tutorial\ngo mod init graphql-go-tutorial\ngo get github.com/99designs/gqlgen@latest\ngo get github.com/99designs/gqlgen/graphql/introspection@latest\nAgora, inicializaremos o gqlgen no projeto. Este comando criará a estrutura básica de arquivos:
go run github.com/99designs/gqlgen init\nApós a execução, você verá a seguinte estrutura:
\n- \n
graph/— diretório com arquivos de esquema e resolvers \ngraph/schema.graphqls— definição do esquema GraphQL \ngraph/resolver.go— stubs para os resolvers \nserver.go— ponto de entrada da aplicação \ngqlgen.yml— configuração do gerador \n
2. Definição do esquema GraphQL
\nAbriremos o arquivo graph/schema.graphqls e definiremos nosso modelo de dados. Como exemplo, criaremos um sistema simples de gerenciamento de tarefas (Task Manager):
type Task {\n id: ID!\n title: String!\n description: String\n status: TaskStatus!\n createdAt: Time!\n}\n\nenum TaskStatus {\n TODO\n IN_PROGRESS\n DONE\n}\n\ntype Query {\n tasks(status: TaskStatus): [Task!]!\n task(id: ID!): Task\n}\n\ntype Mutation {\n createTask(title: String!, description: String): Task!\n updateTask(id: ID!, title: String, description: String, status: TaskStatus): Task!\n deleteTask(id: ID!): Boolean!\n}\n\nscalar Time\nApós salvar o esquema, executaremos a geração de código:
\ngo run github.com/99designs/gqlgen generate\nEste comando criará o arquivo graph/model/models_gen.go com as estruturas Go e atualizará os resolvers.
3. Implementação dos resolvers e lógica de negócio
\nAgora, implementaremos a lógica no arquivo graph/schema.resolvers.go. Primeiro, criaremos um armazenamento simples em memória (in-memory store):
// Em graph/resolver.go adicionaremos o armazenamento\ntype Resolver struct {\n tasks []*model.Task\n mu sync.Mutex\n}\n\nfunc NewResolver() *Resolver {\n return &Resolver{\n tasks: make([]*model.Task, 0),\n }\n}\nAgora, implementaremos os resolvers para Query e Mutation:
\n// Query.Task\nfunc (r *queryResolver) Task(ctx context.Context, id string) (*model.Task, error) {\n r.mu.Lock()\n defer r.mu.Unlock()\n \n for _, task := range r.tasks {\n if task.ID == id {\n return task, nil\n }\n }\n return nil, fmt.Errorf("task not found")\n}\n\n// Mutation.CreateTask\nfunc (r *mutationResolver) CreateTask(ctx context.Context, title string, description *string) (*model.Task, error) {\n r.mu.Lock()\n defer r.mu.Unlock()\n \n task := &model.Task{\n ID: uuid.New().String(),\n Title: title,\n Description: description,\n Status: model.TaskStatusTodo,\n CreatedAt: time.Now(),\n }\n \n r.tasks = append(r.tasks, task)\n return task, nil\n}\n\n// Mutation.UpdateTask\nfunc (r *mutationResolver) UpdateTask(ctx context.Context, id string, title *string, description *string, status *model.TaskStatus) (*model.Task, error) {\n r.mu.Lock()\n defer r.mu.Unlock()\n \n for _, task