
【免费下载链接】howtographqlThe Fullstack Tutorial for GraphQL项目地址https://gitcode.com/gh_mirrors/ho/howtographql点击查看免费下载本篇文章以 How to GraphQL 仓库中 GraphQL Go 后端教程的 Mutations 章节 为骨架讲解 GraphQL Mutation 的基本概念以及如何在 gqlgen 自动生成的schema.resolvers.go中实现createLinkmutation 解析器并在 GraphQL playground 中完成真实的请求/响应验证。读完你将掌握 Mutation 的 schema 定义方式、gqlgen resolver 的函数签名约定、输入类型到业务对象的映射手法以及从内存假实现演进到数据库真实写入的完整路径。什么是 Mutation在 GraphQL 中Mutation变更与 Query查询在形态上几乎一致它们都有操作名称、可以接收参数、也可以返回数据。二者唯一的本质区别在于语义约定——Mutation 用于触发数据写入写操作而 Query 用于读取数据读操作。值得注意的是GraphQL 规范层面并没有强制禁止在 Query 中写入数据技术上完全可以在 Query 的 resolver 里修改数据库。但从工程规范上讲绝不应该这样做客户端可以通过操作名称一眼识别出该请求是否会改变服务端状态从而决定缓存策略与调用方式GraphQL 规范要求 Mutation 根字段的解析必须串行执行而 Query 字段可以并行解析——把写操作放在 Query 中会破坏这种确定性导致难以预期的并发副作用语义混乱会让 API 契约schema失去自解释能力违背 GraphQLschema 即约定的设计初衷。所以凡是要新增、修改、删除数据的操作都应该定义在Mutation类型之下。Mutation 的 Schema 定义与代码生成gqlgen 采用schema 驱动开发先在schema.graphqls中声明类型与操作再运行代码生成命令自动产出 resolver 骨架最后开发者只需填充业务实现。在本教程的 Getting Started 章节 中我们定义了如下核心 schemagraph/schema.graphqlstype Link { id: ID! title: String! address: String! user: User! } type User { id: ID! name: String! } type Query { links: [Link!]! } input NewLink { title: String! address: String! } input RefreshTokenInput{ token: String! } input NewUser { username: String! password: String! } input Login { username: String! password: String! } type Mutation { createLink(input: NewLink!): Link! createUser(input: NewUser!): String! login(input: Login!): String! # well talk about this in authentication section refreshToken(input: RefreshTokenInput!): String! }其中与本文直接相关的是两个声明input NewLink一个输入类型包含title与address两个必填String!字段是客户端提交创建链接数据时使用的参数容器createLink(input: NewLink!): Link!Mutation 根字段接收一个必填的NewLink输入对象返回一个非空Link对象。完成 schema 定义后运行以下命令让 gqlgen 重新生成模型与执行器代码go run github.com/99designs/gqlgen generate生成的关键文件依据 gqlgen 官方说明与本教程结构包括graph/generated/generated.go—— GraphQL 执行运行时生成代码的主体graph/model/models_gen.go—— 根据 schema 生成的模型其中就包含NewLink、Link、User等类型graph/schema.graphqls—— schema 定义文件graph/schema.resolvers.go—— 应用代码所在位置generated.go会调用这里的函数来获取客户端请求的数据server.go—— 最小入口将生成的 GraphQL 服务器挂载到http.Handler上。提示若生成时报validation failed: packages.Load错误通常是 gqlgen 使用了 todo 项目作为起始模板所致。可编辑graph/schema.resolvers.go删除模板自带的CreateTodo与Todos函数后再重新运行生成命令。实现 createLink 解析器第一步查看生成的函数签名打开graph/schema.resolvers.go找到 gqlgen 为createLink生成的 resolver 骨架func (r *mutationResolver) CreateLink(ctx context.Context, input model.NewLink) (*model.Link, error) {逐项拆解这个签名r *mutationResolvermutation 解析器的接收者generated.go会把所有 Mutation 字段解析器聚合在该结构体上ctx context.Context携带请求上下文如认证后的用户信息、链路追踪数据等后续实现鉴权时正是从这里取出当前用户input model.NewLink由 schema 中input NewLink生成的输入类型input.Title、input.Address即为客户端提交的字段值(*model.Link, error)返回值约定。第一个值是对应 schema 返回类型Link!的模型对象第二个值是错误信息供 GraphQL 执行引擎处理错误路径。第二步构造 Link 对象并返回由于本阶段尚未接入数据库数据库将在下一节配置我们暂时只接收NewLink数据、在内存中构造一个Link对象作为响应返回。在函数体内填入func (r *mutationResolver) CreateLink(ctx context.Context, input model.NewLink) (*model.Link, error) { var link model.Link var user model.User link.Address input.Address link.Title input.Title user.Name test link.User user return link, nil }这段代码完成了两个关键动作输入映射把input.NewLink中的Title、Address逐字段复制到model.Link上。schema 中Link.title与Link.address均为非空字段因此必须先赋值才能满足返回类型约束关联对象构造由于Link.user: User!也是非空字段必须同时构造一个model.User并赋值给link.User。这里为了演示先用user.Name test写死一个测试用户名——它将在后续章节被替换为从数据库查询或从认证上下文解析出的真实用户。return link, nil表示解析成功且无错误gqlgen 执行引擎会按照客户端请求的字段选择集序列化该对象。教程正文中的Instruction步骤块是 How to GraphQL 站点的交互式提示组件由 Markdown.tsx 中的JsxParser将INSTRUCTION映射到 Instruction.tsx 渲染阅读时可将其中内容视为动手操作指令。运行服务器并验证 Mutation启动服务器go run server.go浏览器打开 gqlgen 自带的 GraphQL playground默认访问http://localhost:8080/具体端口由server.go中defaultPort决定发送如下 mutation 请求mutation { createLink(input: {title: new link, address:http://address.org}){ title, user{ name } address } }观察返回结果{ data: { createLink: { title: new link, user: { name: test }, address: http://address.org } } }值得注意的细节响应中的title、address与请求输入一致说明输入类型到Link对象的字段映射正确user.name返回test正是 resolver 中写死的测试用户响应字段完全由客户端的选择集决定即使Link类型还包含id字段只要请求中没有选择它响应就不会包含它——这是 GraphQL 按需取数的核心特性也是 Mutation 与 Query 共有的行为。从内存假实现到数据库真实写入以上实现每次都会丢弃输入数据仅返回一个全新构造的对象属于典型的假实现。为了让createLink具备真实持久化能力教程在 数据库章节 配置 MySQL 之后于 Create and Retrieve Links 章节 给出了完整演进第一步在internal/links/links.go中定义数据访问层结构体与方法package links type Link struct { ID string Title string Address string User *users.User } func (link Link) Save() int64 { stmt, err : database.Db.Prepare(INSERT INTO Links(Title,Address) VALUES(?,?)) if err ! nil { log.Fatal(err) } res, err : stmt.Exec(link.Title, link.Address) if err ! nil { log.Fatal(err) } id, err : res.LastInsertId() if err ! nil { log.Fatal(Error:, err.Error()) } log.Print(Row inserted!) return id }这里Save()使用PrepareExec的方式插入记录预编译语句prepared statement既能防御 SQL 注入又能在多次执行相同语句时获得性能收益LastInsertId()则返回自增主键。第二步改写schema.resolvers.go中的CreateLink把内存构造替换为数据库写入func (r *mutationResolver) CreateLink(ctx context.Context, input model.NewLink) (*model.Link, error) { var link links.Link link.Title input.Title link.Address input.Address linkID : link.Save() return model.Link{ID: strconv.FormatInt(linkID, 10), Title:link.Title, Address:link.Address}, nil }这一步揭示了本项目的双 Link 结构体设计links.Link是面向数据库持久化的内部模型model.Link是 gqlgen 根据 schema 生成、面向 GraphQL 客户端的模型二者之间通过 resolver 手动转换数据库自增 ID 需用strconv.FormatInt(linkID, 10)转成 schema 要求的ID!字符串类型。同理上一章的 Links 查询 从写死的 dummy link演进为通过links.GetAll()从数据库读取记录后逐条转换为model.Link。此时再发送同样的 mutation返回结果中的id将是数据库真实生成的自增主键{ data: { createLink: { title: something, address: somewhere, id: 1 } } }小结与下一步通过本篇文章我们完成了从概念到代码的完整闭环知识点要点Mutation 语义与 Query 形态一致有名字、有参数、有返回值但专用于写操作Schema 声明在graph/schema.graphqls中定义Mutation根类型与input输入类型再运行gqlgen generateResolver 签名CreateLink(ctx context.Context, input model.NewLink) (*model.Link, error)ctx 携带请求上下文字段映射从input复制数据构造model.Link非空关联字段需一并构造验证方式go run server.go后在 playground 发送 mutation响应字段由选择集决定持久化演进通过internal/links/links.go的Save()/GetAll()配合 MySQL 与 golang-migrate 实现真实读写现在你已经掌握 Mutation 的实现套路。接下来可以继续阅读 数据库配置章节 了解 MySQL 与迁移脚本的搭建再回到 Create and Retrieve Links 章节 完善真实持久化最终在 认证章节 中将写死的test用户替换为登录后的真实用户——届时ctx context.Context中携带的认证信息将派上用场。赞分享【免费下载链接】howtographqlThe Fullstack Tutorial for GraphQL项目地址https://gitcode.com/gh_mirrors/ho/howtographql点击查看免费下载相关推荐RunAsTI技术深度解析Windows最高权限获取实战指南RunAsTI技术深度解析Windows最高权限获取实战指南 在Windows系统维护和深度管理中权限限制往往是技术人员的最大障碍。RunAsTI作为一款能gqlgen 入门实战用 Go 构建类型安全的 GraphQL 服务器gqlgen 入门实战用 Go 构建类型安全的 GraphQL 服务器 本篇教程基于 gqlgen 官方 Getting Started 指南展开完整演示如后端GraphQL代码生成使用gqlgen实现GraphQL服务认证机制详解使用gqlgen实现GraphQL服务认证机制详解 前言 在现代Web应用中认证机制是保障系统安全的重要组成部分。本文将详细介绍如何在gqlgen框架中实现G后端GraphQL代码生成上一篇Shuffle自动化平台为安全运营而生下一篇探索Mito.js一款轻量级的前端监控SDK创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考