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

news2025/2/1 1:37:43

使用 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 的基础:

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 实现示例:

// 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. 保持自定义实现代码不变

使用以下命令生成代码:

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. 错误处理

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

    defer rows.Close()
    
  4. 时间处理:统一使用 RFC3339 格式处理时间

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

    updatedAtStr := updatedAt.Format(time.RFC3339)
    post.UpdatedAt = &updatedAtStr
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2289115.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

将pandas.core.series.Series类型的小数转化成百分数

大年初二,大家过年好,蛇年行大运! 今天在编写一个代码的时候,使用 import pandas as pd产生了pandas.core.series.Series类型的数据,里面有小数,样式如下: 目的:将这些小数转化为百…

详细解释java当中的所有知识点(前言及数据类型及变量)(第一部分)

会将java当中的所有的知识点以及相关的题目进行分享,这是其中的第一部分,用红色字体标注出重点,以及加粗的方式进行提醒 目录 一、Java语言概述 1.Java语言简介 2.语言优势 二、main方法 1.Java程序结构组成 2.运行Java程序 3.注释 4.…

字节iOS面试经验分享:HTTP与网络编程

字节iOS面试经验分享:HTTP与网络编程 🌟 嗨,我是LucianaiB! 🌍 总有人间一两风,填我十万八千梦。 🚀 路漫漫其修远兮,吾将上下而求索。 目录 字节iOS面试经验分享:HTT…

代码随想录_栈与队列

栈与队列 232.用栈实现队列 232. 用栈实现队列 使用栈实现队列的下列操作: push(x) – 将一个元素放入队列的尾部。 pop() – 从队列首部移除元素。 peek() – 返回队列首部的元素。 empty() – 返回队列是否为空。 思路: 定义两个栈: 入队栈, 出队栈, 控制出入…

【Oracle篇】使用Hint对优化器的执行计划进行干预(含单表、多表、查询块、声明四大类Hint干预)

💫《博主介绍》:✨又是一天没白过,我是奈斯,从事IT领域✨ 💫《擅长领域》:✌️擅长阿里云AnalyticDB for MySQL(分布式数据仓库)、Oracle、MySQL、Linux、prometheus监控;并对SQLserver、NoSQL(…

论文阅读(九):通过概率图模型建立连锁不平衡模型和进行关联研究:最新进展访问之旅

1.论文链接:Modeling Linkage Disequilibrium and Performing Association Studies through Probabilistic Graphical Models: a Visiting Tour of Recent Advances 摘要: 本章对概率图模型(PGMs)的最新进展进行了深入的回顾&…

【Matlab高端绘图SCI绘图模板】第006期 对比绘柱状图 (只需替换数据)

1. 简介 柱状图作为科研论文中常用的实验结果对比图,本文采用了3组实验对比的效果展示图,代码已调试好,只需替换数据即可生成相关柱状图,为科研加分。通过获得Nature配色的柱状图,让你的论文看起来档次更高&#xff0…

YOLOv8源码修改(4)- 实现YOLOv8模型剪枝(任意YOLO模型的简单剪枝)

目录 前言 1. 需修改的源码文件 1.1添加C2f_v2模块 1.2 修改模型读取方式 1.3 增加 L1 正则约束化训练 1.4 在tensorboard上增加BN层权重和偏置参数分布的可视化 1.5 增加剪枝处理文件 2. 工程目录结构 3. 源码文件修改 3.1 添加C2f_v2模块和模型读取 3.2 添加L1正则…

后端token校验流程

获取用户信息 前端中只有 await userStore.getInfo() 表示从后端获取数据 在页面中找到info对应的url地址,在IDEA中查找 这里是getInfo函数的声明,我们要找到这个函数的使用,所以点getInfo() Override public JSONObject getInfo() {JSO…

Ansible自动化运维实战--通过role远程部署nginx并配置(8/8)

文章目录 1、准备工作2、创建角色结构3、编写任务4、准备配置文件(金甲模板)5、编写变量6、编写处理程序7、编写剧本8、执行剧本Playbook9、验证-游览器访问每台主机的nginx页面 在 Ansible 中,使用角色(Role)来远程部…

C语言自定义数据类型详解(二)——结构体类型(下)

书接上回,前面我们已经给大家介绍了如何去声明和创建一个结构体,如何初始化结构体变量等这些关于结构体的基础知识。下面我们将继续给大家介绍和结构体有关的知识: 今天的主题是:结构体大小的计算并简单了解一下位段的相关知识。…

Maven的单元测试

1. 单元测试的基本概念 单元测试(Unit Testing) 是一种软件测试方法,专注于测试程序中的最小可测试单元——通常是单个类或方法。通过单元测试,可以确保每个模块按预期工作,从而提高代码的质量和可靠性。 2.安装和配…

Jetson Xavier NX 安装 CUDA 支持的 PyTorch 指南

本指南将帮助开发者完成在 Jetson Xavier NX 上安装 CUDA 支持的 PyTorch。 安装方法 在 Jetson 上安装 Pytorch 只有两种方法。 一种是直接安装他人已经编译好的 PyTorch 轮子;一种是自己从头开始开始构建 PyTorch 轮子并且安装。 使用轮子安装 可以从我的 Gi…

GWO优化GRNN回归预测matlab

灰狼优化算法(Grey Wolf Optimizer,简称 GWO),是一种群智能优化算法,由澳大利亚格里菲斯大学的 Mirjalii 等人于 2014 年提出。该算法的设计灵感源自灰狼群体的捕食行为,核心思想在于模拟灰狼社会的结构与行…

Unity 粒子特效在UI中使用裁剪效果

1.使用Sprite Mask 首先建立一个粒子特效在UI中显示 新建一个在场景下新建一个空物体,添加Sprite Mask组件,将其的Layer设置为UI相机渲染的UI层, 并将其添加到Canvas子物体中,调整好大小,并选择合适的Sprite&#xff…

【大厂AI实践】OPPO:大规模知识图谱及其在小布助手中的应用

导读:OPPO知识图谱是OPPO数智工程系统小布助手团队主导、多团队协作建设的自研大规模通用知识图谱,目前已达到数亿实体和数十亿三元组的规模,主要落地在小布助手知识问答、电商搜索等场景。 本文主要分享OPPO知识图谱建设过程中算法相关的技…

C# 添加、替换、提取、或删除Excel中的图片

在Excel中插入与数据相关的图片,能将关键数据或信息以更直观的方式呈现出来,使文档更加美观。此外,对于已有图片,你有事可能需要更新图片以确保信息的准确性,或者将Excel 中的图片单独保存,用于资料归档、备…

赛博算卦之周易六十四卦JAVA实现:六幺算尽天下事,梅花化解天下苦。

佬们过年好呀~新年第一篇博客让我们来场赛博算命吧! 更多文章:个人主页 系列文章:JAVA专栏 欢迎各位大佬来访哦~互三必回!!! 文章目录 #一、文化背景概述1.文化起源2.起卦步骤 #二、卦象解读#三、just do i…

iperf 测 TCP 和 UDP 网络吞吐量

注:本文为 “iperf 测网络吞吐量” 相关文章合辑。 未整理去重。 使用 iperf3 监测网络吞吐量 Tom 王 2019-12-21 22:23:52 一 iperf3 介绍 (1.1) iperf3 是一个网络带宽测试工具,iperf3 可以擦拭 TCP 和 UDP 带宽质量。iperf3 可以测量最大 TCP 带宽…

内外网文件摆渡企业常见应用场景和对应方案

在如今的企业环境中,内外网文件摆渡的需求越来越常见,也变得越来越重要。随着信息化的不断推进,企业内部和外部之间的数据交换越来越频繁,如何安全、高效地进行文件传输成了一个关键问题。今天,咱就来聊聊内外网文件摆…