当前位置: 首页 > news >正文

oracle自定义异常标量,gqlgen/graphql自定义标量

昨天,我们在使用gqlgen的时候,发现它默认没有int64类型的标量,只有int类型的标量。所以需要自定义一个int64标量。

先说一下自定义标量的原理吧,这个在文档里面没有去解释,只是给出了一段代码,其他的就要自己去理解了。

自定义标量的原理就是,前端传递一个字符串,然后gqlgen会自动调用我们实现的解析函数,去解析这个字符串,得到我们想要的类型。

现在,我们来实战一下。我们初始化项目:

1

2

3~/codeDir/golangCode # mkdir scalars ; cd scalars ; go mod init scalars

go: creating new go.mod: module scalars

~/codeDir/golangCode/scalars #

这里,我们是通过go module这个包依赖管理工具来管理的。

因为gqlgen是先定义schema的然后再生成代码的,所以,我们需要先定义好我们的schema。我们先创建文件:

1~/codeDir/golangCode/scalars # touch schema.graphql

内容如下:

1

2

3

4

5

6

7type Article {

id: ID!

text: String!

}

type Query {

article: Article!

}

这里,我们简单的定义了一个类型Article和一个查询article。

OK,现在我们来生成一下我们的代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16~/codeDir/golangCode/scalars # gqlgen init

Exec "go run ./server/server.go" to start GraphQL server

~/codeDir/golangCode/scalars # tree

.

├── generated.go

├── go.mod

├── go.sum

├── gqlgen.yml

├── models_gen.go

├── resolver.go

├── schema.graphql

└── server

└── server.go

1 directory, 8 files

~/codeDir/golangCode/scalars #

我们可以在resolver.go的Article函数里面写我们的查询,这里,我们简单的返回一条记录即可:

1

2

3

4

5

6func (r *queryResolver) Article(ctx context.Context) (*Article, error) {

return &Article{

ID: "1",

Text: "I am codinghuang",

}, nil

}

然后,我们启动服务器:

1

2

3~/codeDir/golangCode/scalars # go run server/server.go

2019/08/30 02:04:46 connect to http://localhost:8080/ for GraphQL playground

然后,我们在浏览器里面做如下请求:

1

2

3

4

5

6

7# Write your query or mutation here

query {

article {

id

text

}

}

我们将会得到如下结果:

1

2

3

4

5

6

7

8{

"data": {

"article": {

"id": "1",

"text": "I am codinghuang"

}

}

}

现在,我们来给article增加一个查询参数,比如说时间,我们这里假定是int64这个标量。我们修改schema:

1

2

3

4

5

6

7

8

9

10

11scalar Int64

type Article {

id: ID!

text: String!

time: Int64!

}

type Query {

article (time: Int64): Article!

}

然后,我们需要去实现这个Int64标量。我们创建一个新的文件,叫做int64.go:

1~/codeDir/golangCode/scalars # touch int64.go

内容如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18package scalars

import (

"io"

)

// Int64 is int64

type Int64 int64

// UnmarshalGQL implements the graphql.UnMarshaler interface

func (i *Int64) UnmarshalGQL(v interface{}) error {

return nil

}

// MarshalGQL implements the graphql.Marshaler interface

func (i Int64) MarshalGQL(w io.Writer) {

return

}

我们需要去实现这里的UnmarshalGQL函数和MarshalGQL函数。这里,我们先简单的做个小测试,实现如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20package scalars

import (

"io"

)

// Int64 is int64

type Int64 int64

// UnmarshalGQL implements the graphql.UnMarshaler interface

func (i *Int64) UnmarshalGQL(v interface{}) error {

*i = 10

return nil

}

// MarshalGQL implements the graphql.Marshaler interface

func (i Int64) MarshalGQL(w io.Writer) {

w.Write([]byte("5"))

return

}

然后,我们需要去修改gqlgen.yml文件,指明我们的这个自定义的标量:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17# .gqlgen.yml example

#

# Refer to https://gqlgen.com/config/

# for detailed .gqlgen.yml documentation.

schema:

- schema.graphql

exec:

filename: generated.go

model:

filename: models_gen.go

resolver:

filename: resolver.go

type: Resolver

models:

Int64:

model: scalars.Int64

然后,我们需要把resolver.go文件删除:

1~/codeDir/golangCode/scalars # rm resolver.go

然后重新生成:

1~/codeDir/golangCode/scalars # gqlgen

我们会发现,此时Article这个queryResolver多了一个参数time *Int64,注意,这里的Int64是我们scalars包下自定义的那个Int64,而不是golang自带的那个int64。

OK,我们重新写一下这个Article函数:

1

2

3

4

5

6

7

8func (r *queryResolver) Article(ctx context.Context, time *Int64) (*Article, error) {

fmt.Println(*time)

return &Article{

ID: "1",

Text: "I am codinghuang",

Time: *time,

}, nil

}

然后,我们重新启动服务器:

1

2

3~/codeDir/golangCode/scalars # go run server/server.go

2019/08/30 02:23:25 connect to http://localhost:8080/ for GraphQL playground

我们发起如下请求,我们传递了一个时间参数"1":

1

2

3

4

5

6

7

8# Write your query or mutation here

query {

article (time: "1") {

id

text

time

}

}

会得到如下的结果:

1

2

3

4

5

6

7

8

9{

"data": {

"article": {

"id": "1",

"text": "I am codinghuang",

"time": 5

}

}

}

我们发现,返回的这个时间5实际上就是我们在int64.go文件里面实现的:

1

2

3

4func (i Int64) MarshalGQL(w io.Writer) {

w.Write([]byte("5"))

return

}

也就是说,我们w io.Writer里面写了什么内容,就会返回给前端。

我们再看看终端的输出:

1

2

3

4~/codeDir/golangCode/scalars # go run server/server.go

2019/08/30 02:28:40 connect to http://localhost:8080/ for GraphQL playground

10

打印出了10,而不是客户端传递给服务器的1。这个10其实就是我们再int64.go文件里面实现的:

1

2

3

4

5// UnmarshalGQL implements the graphql.UnMarshaler interface

func (i *Int64) UnmarshalGQL(v interface{}) error {

*i = 10

return nil

}

也就是说,我们在*i里面填写的值,可以被Article queryResolver的time *Int64获取到。

OK,那我们如何获取到前端传递过来的time呢?

我们对int.go里面的UnmarshalGQL函数做如下修改:

1

2

3

4

5

6

7

8

9

10

11// UnmarshalGQL implements the graphql.UnMarshaler interface

func (i *Int64) UnmarshalGQL(v interface{}) error {

str, ok := v.(string)

if !ok {

return errors.New("time must be string")

}

n, err := strconv.ParseInt(str, 10, 64)

*i = Int64(n)

return err

}

也就是说,前端传递给服务器的参数,我们可以在v interface{}里面获取到。

然后重新启动服务器:

1

2

3~/codeDir/golangCode/scalars # go run server/server.go

2019/08/30 02:36:26 connect to http://localhost:8080/ for GraphQL playground

然后做如下请求:

1

2

3

4

5

6

7

8# Write your query or mutation here

query {

article (time: 1) {

id

text

time

}

}

结果:

1

2

3

4

5

6

7

8

9

10

11{

"errors": [

{

"message": "time must be string",

"path": [

"article"

]

}

],

"data": null

}

因为我们在UnmarshalGQL里面限定了time必须为string。

我们修改请求如下:

1

2

3

4

5

6

7

8

9# Write your query or mutation here

query {

article (time: "100") {

id

text

time

}

}

结果:

1

2

3

4

5

6

7

8

9{

"data": {

"article": {

"id": "1",

"text": "I am codinghuang",

"time": 5

}

}

}

我来看看终端的输出:

1

2

3

4~/codeDir/golangCode/scalars # go run server/server.go

2019/08/30 02:36:26 connect to http://localhost:8080/ for GraphQL playground

100

说明我们在reoslver里面获取到了客户端传递的这个时间字符串100,并且成功的转换为了我们自定义的Int64类型。

所以,对于自定义标量,总结下了实际上就是:

1

2

3

4

51、先定义好我们的两个解析函数

2、客户端传递一个自定义标量的参数,那么就会调用我们的UnmarshalGQL解析函数,把前端传递过来的值转化为我们自定义的标量类型(至于这里我们需不需要去限定客户端传递过来的是字符串还是整数,看个人情况吧,在我的例子里面,其实不可以不对传递的参数做字符串的要求,完全可以传递一个整数过来)

然后,resolver就可以通过参数获取到我们在UnmarshalGQL解析函数里面设置的那个值

3、服务器返回给客户端的值,首先会经过MarshalGQL解析函数处理,然后再通过io.Writer写入我们需要返回给前端的值。

4、这一切,gqlgen都会帮我们自动的调用

最后,GraphQL好用。

相关文章:

  • oracle安装出现连接失败怎么办,oracle客户端PLSQL连接失败解决方法
  • oracle数据库架ssm,GitHub - wind0926/ssm-maven: smm框架+maven+oracle的旅游后台系统
  • oracle快速生成一千万条数据,[Oracle]快速生成大量模拟数据的方法
  • oracle存储过程生成uuid,存储过程 根据uuid
  • oracle submit_time,Oracle '26-2月 -19 03.34.47.000000 下午' 字符串日期解析
  • linux 计算字符串日期,在linux下获取时间字符串
  • linux 阻止 复位命令,Linux下锁定账号,禁止登录系统的设置总结
  • Linux怎么看每一级别的权限,linux 特殊权限chattr(文件系统级别的权限) Attr 权限和 ACL访问控制列表 ......
  • 改文件命名linux,linux下修改文件名称
  • 小米网卡驱动linux,小米笔记本pro 15.6寸安装ubuntu16.04无法使用wifi的解决方法
  • fopen函数在linux,Fopen()是Linux中的一个线程安全函数吗?
  • linux vnc登录日志,CentOS安装使用VNC进行远程桌面登录
  • 鸟哥linux视频教程密码,[鸟哥linux视频教程整理]04_01_Linux用户管理命令详解
  • linux memcpy 地址对齐,在memcpy中对齐源地址和目标地址
  • 红帽企业级Linux.As版,晋级Linux中的默认JDK的版本
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  • 4. 路由到控制器 - Laravel从零开始教程
  • E-HPC支持多队列管理和自动伸缩
  • EventListener原理
  • Java 最常见的 200+ 面试题:面试必备
  • JavaScript函数式编程(一)
  • Javascript设计模式学习之Observer(观察者)模式
  • Laravel Mix运行时关于es2015报错解决方案
  • Mocha测试初探
  • nodejs实现webservice问题总结
  • Python - 闭包Closure
  • uni-app项目数字滚动
  • 包装类对象
  • 浮动相关
  • 关于springcloud Gateway中的限流
  • 开发基于以太坊智能合约的DApp
  • 如何编写一个可升级的智能合约
  • 如何借助 NoSQL 提高 JPA 应用性能
  • 手机端车牌号码键盘的vue组件
  • 算法系列——算法入门之递归分而治之思想的实现
  • 微服务框架lagom
  • 学习使用ExpressJS 4.0中的新Router
  • 一个完整Java Web项目背后的密码
  • 【运维趟坑回忆录 开篇】初入初创, 一脸懵
  • 【运维趟坑回忆录】vpc迁移 - 吃螃蟹之路
  • ​LeetCode解法汇总2304. 网格中的最小路径代价
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • ​你们这样子,耽误我的工作进度怎么办?
  • $.each()与$(selector).each()
  • (附源码)python房屋租赁管理系统 毕业设计 745613
  • (利用IDEA+Maven)定制属于自己的jar包
  • (顺序)容器的好伴侣 --- 容器适配器
  • .NET 指南:抽象化实现的基类
  • .NET 中使用 TaskCompletionSource 作为线程同步互斥或异步操作的事件
  • .NET建议使用的大小写命名原则
  • .NET应用架构设计:原则、模式与实践 目录预览
  • .NET中使用Protobuffer 实现序列化和反序列化
  • [2013][note]通过石墨烯调谐用于开关、传感的动态可重构Fano超——
  • [Angular] 笔记 20:NgContent
  • [AutoSar]BSW_Com07 CAN报文接收流程的函数调用