Go-Zero定义API实战:探索API语法规范与最佳实践(五)
前言
上一篇文章带你实现了Go-Zero模板定制化,本文将继续分享如何使用GO-ZERO进行业务开发。
通过编写API层,我们能够对外进行接口的暴露,因此学习规范的API层编写姿势是很重要的。
通过本文的分享,你将能够学习到Go-Zero的API语法规范,以及学会实际上手使用。
概述
下文所说的是 api 是 go-zero 自研的领域特性语言(下文称 api 语言 或 api 描述语言),旨在实现人性化的基础描述语言,作为生成 HTTP 服务最基本的描述语言。
api 领域特性语言包含语法版本、info 块、结构体声明、服务描述等几大块语法组成,其中结构体和 Golang 结构体 语法几乎一样,只是移除了 struct 关键字。
实战前准备
首先需要你在本地安装goctl、go-zero,下载教学和地址点击这里,按照教程操作即可,非常简单。
下面按顺序和我操作吧,对使用模板快速生成API层不清楚的同学务必先看我前篇文章:Go-Zero goctl实战
这里我假设你已经创建好了一个API服务的demo,且目录结构长这样:

学习API语法
对于Go语言开发者来说,Go-Zero的API语法学习和理解成本极低,我们可以很轻松的学会API语法。下面我会为大家介绍重点需要掌握的语法。更详细的语法规范,可以参考官网:API 规范 | go-zero Documentation
生成API文件
cd demo
goctl api go -api demo.api -dir . -style gozero
- 基础的API文件

ID标识符
golang中的预定义类型、常量、函数,以及关键字在api里面同样适用
- 预定义
//预定义类型:
any bool byte comparable
complex64 complex128 error float32 float64
int int8 int16 int32 int64 rune string
uint uint8 uint16 uint32 uint64 uintptr
//预定义常量:
true false iota
//零值:
nil
//预定义函数:
append cap close complex copy delete imag len
make new panic print println real recover
- 关键字
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var
tip:需要注意的是 goctl api不支持any类型!!!
类型声明
规则
- 类型声明必须以
type开头 - 不需要声明
struct关键字 - 不支持嵌套结构体声明
- 不支持别名
示例
type StructureExample {
// 基本数据类型示例
BaseInt int `json:"base_int"`
BaseBool bool `json:"base_bool"`
BaseString string `json:"base_string"`
BaseByte byte `json:"base_byte"`
BaseFloat32 float32 `json:"base_float32"`
BaseFloat64 float64 `json:"base_float64"`
// 切片示例
BaseIntSlice []int `json:"base_int_slice"`
BaseBoolSlice []bool `json:"base_bool_slice"`
BaseStringSlice []string `json:"base_string_slice"`
BaseByteSlice []byte `json:"base_byte_slice"`
BaseFloat32Slice []float32 `json:"base_float32_slice"`
BaseFloat64Slice []float64 `json:"base_float64_slice"`
// map 示例
BaseMapIntString map[int]string `json:"base_map_int_string"`
BaseMapStringInt map[string]int `json:"base_map_string_int"`
BaseMapStringStruct map[string]*StructureExample `json:"base_map_string_struct"`
BaseMapStringIntArray map[string][]int `json:"base_map_string_int_array"`
// 匿名示例
*Base
// 指针示例
Base4 *Base `json:"base4"`
// 新的特性( goctl >= 1.5.1 版本支持 )
// 标签忽略示例
TagOmit string
}
路由前缀
我们可以通过prefix关键字区分路由组

接着再使用goctl api生成代码以及swagger,将swagger导入apifox查看路由前缀,可以看见就增添了前缀/demo。
不知道怎么生成api代码的同学可以看我往期的gozero实战分享——go-zero goctl实战

服务分组
当我们的业务体量上来后,服务接口也会越来越多,生成的代码文件(handler、logic文件等)也会越来越多。这时候我们就需要对不同的接口按一定的分组进行区分,用文件夹进行隔离,以便于开发和维护。
- 分组前的目录结构是这样的

- 我们先将生成的handler和logic文件删除。
- 只需要在@server语句块里面添加关键字group就能进行分组。分组后的结构如下图所示。

JWT校验
- 接下来我们再来看一下api文件中怎么开启jwt认证
- 在配置文件demo-api.yaml中添加jwt配置

- 在config文件中添加一个JWT认证需要的密钥和过期时间配置
JwtAuth struct { // JWT 认证需要的密钥和过期时间配置
AccessSecret string
AccessExpire int64
}

- 使用方法也很简单,我们在@service语句块中添加jwt关键字,使用Auth即可开启jwt。

- 通过测试请求我们可以看见返回401没有权限,说明jwt校验生效了

路由规则
- 路由必须以
/开头 2. 路由节点必须以/分隔 - 路由节点中可以包含
:,但是:必须是路由节点的第一个字符,:后面的节点值必须要在结请求体中有pathtag 声明,用于接收路由参数,详细规则可参考 路由参数。 4. 路由节点可以包含字母、数字(goctl 1.5.1支持,可参考新版 API 解析器使用)、下划线、中划线
参数规则
| 接收规则 | 说明 | 生效范围 | 示例 |
|---|---|---|---|
| json | json 序列化 | 请求体&响应体 | json:"foo" |
| path | 路由参数 | 请求体 | path:"id" |
| form | post 请求的表单(支持 content-type 为 form-data 和 x-www-form-urlencoded) 参数请求接收标识,get 请求的 query 参数接收标识 |
请求体 | form:"name" |
| header | http 请求体接收标识 | 请求体 | header:"Content-Length" |
中间件声明
- 想要使用中间件,可以在@server语句块中使用关键字middleware生成一个中间件模板。
- TIP:需要注意的是中间件首字母必须大写,否则无法被其他包导入。

- 在svc包的servicecontext.go中注册中间件

- 生成的中间件代码如下

API Import
- 当我们的业务体量上来后,api文件可能会越来越大,又或者我们有一些公共结构体。如果我们都写在同一个api文件中,那么api文件将会变得非常巨大,不易阅读和维护,这时候就需要拆解api文件,通过import来导入。
syntax
- 版本信息,import中的版本信息必须与被import的api版本信息一样。
- 规范写法
syntax = "v1"
- 我们创建一个新的文件demo1.api,并且将分组而写到这个api文件下。
- 因为我们的请求体和响应体是公共结构体,都写在demo.api下面了,我们通过import "demo.api"就能导入demo.api。

完整的api文件模板
syntax = "v1"
type Request {
Name string `path:"name,options=you|me"`
}
type Response {
Message string `json:"message"`
}
@server (
prefix :/demo
group: demo_api
jwt: JwtAuth
middleware: Demo_middleware
)
// 分组1的服务
service demo-api {
@handler DemoHandler
post /from (Request) returns (Response)
}
// 分组2的服务
@server (
prefix :/demo1
group: demo_api1
)
service demo-api {
@handler DemoHandler1
get /from/:name(Request) returns (Response)
}
总结
这篇文章详细介绍了如何使用Go-Zero进行API的定义,并进行了实际演示。希望对你有帮助。
我将继续更新Go-Zero系列文章,如果你对Go语言或者微服务感兴趣,欢迎关注我,也欢迎直接私信我。
Go-Zero定义API实战:探索API语法规范与最佳实践(五)的更多相关文章
- paip.复制文件 文件操作 api的设计uapi java python php 最佳实践
paip.复制文件 文件操作 api的设计uapi java python php 最佳实践 =====uapi copy() =====java的无,要自己写... ====php copy ...
- 快读《ASP.NET Core技术内幕与项目实战》WebApi3.1:WebApi最佳实践
本节内容,涉及到6.1-6.6(P155-182),以WebApi说明为主.主要NuGet包:无 一.创建WebApi的最佳实践,综合了RPC和Restful两种风格的特点 1 //定义Person类 ...
- 构建你的长寿命的API第1部分:规范驱动的API开发
构建你的长寿命的API第1部分:规范驱动的API开发 这篇文章是由MuleSoft的Mike Stowe在nginx.conf 2016公布的演示文稿改编的.第一部分重点是规范驱动的API开发. 第二 ...
- 【原创】Docker实战 Dockerfile最佳实践&&容器之间通信
官方最佳实践文档 https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#from Docker实战(三十) ...
- Kafka之 API实战
Kafka之 API实战 一.环境准备 1)启动zk和kafka集群,在kafka集群中打开一个消费者 [hadoop1 kafka]$ bin/kafka-console-consumer.sh \ ...
- 百度AI开放平台- API实战调用
百度AI开放平台- API实战调用 一. 前言 首先说一下项目需求. 两个用户,分别上传了两段不同的文字,要计算两段文字相似度有多少,匹配数据库中的符合条件的数据,初步估计列出来会有60-1 ...
- 集合 数组 定义 转换 遍历 Arrays API MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- (转)RESTful API 设计最佳实践
原文:http://www.oschina.net/translate/best-practices-for-a-pragmatic-restful-api 数据模型已经稳定,接下来你可能需要为web ...
- lumen 构建api(dingo api)
什么是 API API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力, ...
- HTML5之本地文件系统API - File System API
HTML5之本地文件系统API - File System API 新的HTML5标准给我们带来了大量的新特性和惊喜,例如,画图的画布Canvas,多媒体的audio和video等等.除了上面我们提到 ...
随机推荐
- AtCoder Beginner Contest 220
传送门 A.B.C.D.F比较简单,没必要写出来 E - Distance on Large Perfect Binary Tree 题目 问一个深度为 \(n\)的满二叉树有多少个点对的距离恰好为 ...
- OpenHarmony源码解析之电话子系统——通话流程
(以下内容来自开发者分享,不代表 OpenHarmony 项目群工作委员会观点) 王大鹏 深圳开鸿数字产业发展有限公司 一.简介 OpenAtom OpenHarmony(以下简称"Open ...
- Java 包装类:原始数据类型与迭代器
Java Iterator Iterator 接口提供了一种迭代集合的方法,即顺序访问集合中的每个元素.它支持 hasNext() 和 next() 方法,用于检查是否存在下一个元素以及获取下一个元素 ...
- Nacos 多个实例的服务调用失败
在微服务开发阶段,开发人员会频繁启动服务. 这样Nacos上会经常出现一个服务存在多个实例,这是自己和其他同事都启动了同一个服务造成的. 此时使用OpenFeign对该服务进行远程调用,会有很大概率出 ...
- 机器学习&深度学习 操作tips
1. 在运行程序时,报错如下: usage: run.py [-h] --model MODEL [--embedding EMBEDDING] [--word WORD] run.py: error ...
- MogDB/OpenGauss数据库中通过参数控制抓取慢sql
MogDB/OpenGauss 数据库中通过参数控制抓取慢 sql 本文出处:https://www.modb.pro/db/221556 mogdb 数据库中可以通过打开相应的参数抓取慢 sql,该 ...
- 官方直播丨“Hello Ability:从页面跳转开始”周三晚不见不散
12月8日 19:00-20:30,Hello HarmonyOS系列课程的第四期"Hello Ability:从页面跳转开始"线上直播,将带你学习如何快速通过JS page间.A ...
- Python3学习--正则表达式
import rer = re.match("Chen\d+","Chen123ronghua123")r = re.match(".+", ...
- native react 代码智能提示
背景 在vscode 中,虽然有插件可以达到代码提示的效果但是不是很嗨. 所以加上这些: 全局安装typings: npm install typings -g 1 安装react和react-nat ...
- 力扣175(MySQL)-组合两个表(简单)
题目: 表: Person 表: Address 编写一个SQL查询来报告 Person 表中每个人的姓.名.城市和州.如果 personId 的地址不在 Address 表中,则报告为空 null ...