目录

使用 Go 和 gqlgen 实现 GraphQL API:实战指南

使用 Go 和 gqlgen 实现 GraphQL API:实战指南

在本文中,我将分享如何使用 Go 语言和 gqlgen 框架实现一个完整的 GraphQL API。我们将构建一个包含用户、文章和评论功能的博客系统 API。

技术栈

  • Go
  • gqlgen (GraphQL 框架)
  • MySQL (数据存储)
  • Redis (缓存,可选)

项目结构

复制代码
go_graphql/
├── config/
│   └── database.go     # 数据库配置
├── graph/
│   ├── model/          # 数据模型
│   ├── schema.graphqls # GraphQL schema
│   └── schema.resolvers.go # Resolver 实现
├── server.go           # 主程序入口
└── gqlgen.yml         # gqlgen 配置文件

GraphQL Schema 设计

首先,我们需要定义 GraphQL schema,这是整个 API 的基础:

graphql 复制代码
type User {
  id: ID!
  username: String!
  email: String!
  avatar: String
  createdAt: String!
  posts: [Post!]
  comments: [Comment!]
}

type Post {
  id: ID!
  title: String!
  content: String!
  author: User!
  category: Category!
  createdAt: String!
  updatedAt: String
  comments: [Comment!]
  images: [Image!]
}

type Comment {
  id: ID!
  content: String!
  author: User!
  post: Post!
  createdAt: String!
}

type Query {
  users: [User!]!
  user(id: ID!): User
  posts(categoryId: ID): [Post!]!
  post(id: ID!): Post
}

type Mutation {
  createUser(input: CreateUserInput!): User!
  createPost(input: CreatePostInput!): Post!
  createComment(input: CreateCommentInput!): Comment!
}

Resolver 实现

下面是一个完整的用户查询 resolver 实现示例:

go 复制代码
// Users resolver 实现
func (r *queryResolver) Users(ctx context.Context) ([]*model.User, error) {
    rows, err := config.DB.Query(`
        SELECT id, username, email, avatar, created_at 
        FROM users`)
    if err != nil {
        return nil, fmt.Errorf("failed to query users: %v", err)
    }
    defer rows.Close()

    var users []*model.User
    for rows.Next() {
        var user model.User
        var createdAt time.Time
        err := rows.Scan(&user.ID, &user.Username, &user.Email, 
                        &user.Avatar, &createdAt)
        if err != nil {
            return nil, fmt.Errorf("failed to scan user: %v", err)
        }
        user.CreatedAt = createdAt.Format(time.RFC3339)
        users = append(users, &user)
    }
    return users, nil
}

// User 类型的 posts 字段 resolver
func (r *userResolver) Posts(ctx context.Context, obj *model.User) ([]*model.Post, error) {
    rows, err := config.DB.Query(`
        SELECT p.id, p.title, p.content, p.created_at, p.updated_at, 
               p.category_id, p.author_id 
        FROM posts p 
        WHERE p.author_id = ?`, obj.ID)
    if err != nil {
        return nil, fmt.Errorf("failed to query posts: %v", err)
    }
    defer rows.Close()

    var posts []*model.Post
    for rows.Next() {
        var post model.Post
        var createdAt, updatedAt time.Time
        var categoryID, authorID string
        err := rows.Scan(&post.ID, &post.Title, &post.Content, 
                        &createdAt, &updatedAt, &categoryID, &authorID)
        if err != nil {
            return nil, fmt.Errorf("failed to scan post: %v", err)
        }
        post.CreatedAt = createdAt.Format(time.RFC3339)
        updatedAtStr := updatedAt.Format(time.RFC3339)
        post.UpdatedAt = &updatedAtStr
        posts = append(posts, &post)
    }
    return posts, nil
}

代码生成

gqlgen 是一个强大的 GraphQL 代码生成工具,它可以:

  1. 根据 schema 自动生成 Go 类型
  2. 生成所有必要的接口和类型定义
  3. 保持自定义实现代码不变

使用以下命令生成代码:

bash 复制代码
go run github.com/99designs/gqlgen generate

生成的代码包括:

  • graph/generated/generated.go: 包含所有生成的接口和类型
  • graph/model/models_gen.go: 包含根据 schema 生成的 Go 结构体
  • graph/schema.resolvers.go: 包含 resolver 实现的框架代码

最佳实践

  1. 类型安全:利用 Go 的类型系统和 gqlgen 的代码生成确保类型安全

  2. 错误处理

    go 复制代码
    if err != nil {
        return nil, fmt.Errorf("failed to query users: %v", err)
    }
  3. 资源清理:使用 defer 确保资源正确释放

    go 复制代码
    defer rows.Close()
  4. 时间处理:统一使用 RFC3339 格式处理时间

    go 复制代码
    createdAt.Format(time.RFC3339)
  5. 空值处理:对可选字段使用指针类型

    go 复制代码
    updatedAtStr := updatedAt.Format(time.RFC3339)
    post.UpdatedAt = &updatedAtStr
本文是转载文章,点击查看原文
如有侵权,请联系 xyy@jishuzhan.net 删除
相关推荐
小白学大数据35 分钟前
Python自动化爬虫:Scrapy+APScheduler定时任务
开发语言·爬虫·python·自动化
hello_simon1 小时前
小白工具视频转gif,支持在线gif或视频互转,批量转换,免费在线使用,无需下载
开发语言·php·音视频
越城1 小时前
C语言超详细指针知识(三)
c语言·开发语言
island13141 小时前
【QT】QT界面的美容院 -- QSS
开发语言·qt
蹦蹦跳跳真可爱5891 小时前
Python----机器学习(基于PyTorch的蘑菇逻辑回归)
开发语言·人工智能·pytorch·python·机器学习·逻辑回归
Y1nhl1 小时前
力扣hot100_技巧_python版本
开发语言·python·算法·力扣
martian6652 小时前
C++算法优化实战:破解性能瓶颈,提升程序效率
开发语言·c++·性能优化
东方醴歌2 小时前
本地Docker部署开源AI功能笔记Blinko并实现跨网络环境远程使用
开发语言·后端·golang
明天不下雨(牛客同名)2 小时前
Go语言Slice切片底层
开发语言·后端·golang
溟洵3 小时前
【C++ Qt】认识Qt、Qt 项目搭建流程(图文并茂、通俗易懂)
开发语言·c++·qt