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

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

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

开始课程

介绍

GraphQL 是一种用于 API 的现代查询语言,由 Facebook 开发。与 REST 不同,它允许客户端仅请求所需的数据,从而减少网络负载并加速开发。在本教程中,我们将使用流行的 gqlgen 库,在 Go (Golang) 中创建一个完整的 GraphQL API。您将学习如何配置服务器、定义模式、编写解析器以及执行查询。本文面向熟悉 Go 基础的开发者,但即使是新手,也能通过详细的注释完成这些步骤。



1. 项目设置与依赖安装

首先,我们创建一个新的 Go 项目并安装必要的包。



步骤 1: 初始化模块

mkdir graphql-go-tutorialcd graphql-go-tutorialgo mod init graphql-go-tutorial


步骤 2: 安装 gqlgen

gqlgen 是 Go 的 GraphQL 代码生成器。它会根据模式自动创建解析器。

go get github.com/99designs/gqlgen@latest


步骤 3: 生成项目骨架

运行初始化命令:

go run github.com/99designs/gqlgen init

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

  • graph/ — 包含模式和解析器的文件夹
  • server.go — 入口点
  • gqlgen.yml — 生成器配置


2. 定义 GraphQL 模式

模式(schema)描述了 API 的数据类型和操作。打开文件 graph/schema.graphqls 并将其内容替换为以下内容:

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}

这里我们定义了:

  • User — 包含 id、name、email、age 字段的对象。
  • Query — 读取操作(获取所有用户或按 ID 获取单个用户)。
  • Mutation — 写入操作(创建、更新、删除)。

保存后,运行代码生成:

go run github.com/99designs/gqlgen generate

这将创建文件 models_gen.go(Go 类型)和 generated.go(解析器接口)。



3. 实现解析器和数据存储

现在需要编写处理查询的逻辑。为简单起见,我们将数据存储在内存中(结构体切片)。



步骤 1: 创建存储

创建文件 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

博客

书籍推荐