使用 Go 构建 GraphQL API:逐步实践教程

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:为什么 GraphQL 和 Go 是理想组合

\n

在现代 Web 开发中,GraphQL 已成为创建灵活高效 API 的标准。结合以其高性能和简洁性著称的 Go 语言 (Golang),您将获得一个强大的后端开发工具。在本逐步教程中,我们将使用流行的 gqlgen 库,从零开始使用 Go 构建一个完整的 GraphQL API。

\n

您将学习如何配置项目、定义模式、实现解析器以及添加用于身份验证的中间件。到文章结束时,您将拥有一个可运行的 API,随时可与任何前端集成。

\n\n

1. 项目设置与依赖安装

\n

首先,创建一个新的 Go 模块并安装必要的包。请确保您已安装 Go 1.18 或更高版本。

\n
mkdir 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
\n

现在,在项目中初始化 gqlgen。此命令将创建基本的文件结构:

\n
go run github.com/99designs/gqlgen init
\n

执行后,您将看到以下结构:

\n
    \n
  • graph/ — 包含模式文件和解析器的目录
  • \n
  • graph/schema.graphqls — GraphQL 模式定义
  • \n
  • graph/resolver.go — 解析器的占位符
  • \n
  • server.go — 应用程序入口点
  • \n
  • gqlgen.yml — 生成器配置
  • \n
\n\n

2. 定义 GraphQL 模式

\n

打开 graph/schema.graphqls 文件并定义我们的数据模型。作为示例,我们将创建一个简单的任务管理系统 (Task Manager):

\n
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
\n

保存模式后,运行代码生成:

\n
go run github.com/99designs/gqlgen generate
\n

此命令将创建包含 Go 结构体的 graph/model/models_gen.go 文件,并更新解析器。

\n\n

3. 实现解析器和业务逻辑

\n

现在,在 graph/schema.resolvers.go 文件中实现逻辑。首先,创建一个简单的内存存储 (in-memory store):

\n
// 在 graph/resolver.go 中添加存储\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}
\n

现在,实现 Query 和 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                

博客

书籍推荐