写点什么

Go-Zero 定义 API 实战:探索 API 语法规范与最佳实践(五)

作者:王中阳Go
  • 2024-05-14
    北京
  • 本文字数:2938 字

    阅读完需:约 10 分钟

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 校验生效了


路由规则

  1. 路由必须以 / 开头 2. 路由节点必须以 / 分隔

  2. 路由节点中可以包含 :,但是 : 必须是路由节点的第一个字符,: 后面的节点值必须要在结请求体中有 path tag 声明,用于接收路由参数,详细规则可参考 路由参数。 4. 路由节点可以包含字母、数字(goctl 1.5.1 支持,可参考 新版 API 解析器使用)、下划线、中划线

参数规则

中间件声明

  • 想要使用中间件,可以在 @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 语言或者微服务感兴趣,欢迎关注我,也欢迎直接私信我。

发布于: 16 分钟前阅读数: 5
用户头像

王中阳Go

关注

靠敲代码在北京买房的程序员 2022-10-09 加入

【微信】wangzhongyang1993【公众号】程序员升职加薪之旅【成就】InfoQ专家博主👍掘金签约作者👍B站&掘金&CSDN&思否等全平台账号:王中阳Go

评论 (1 条评论)

发布
用户头像
文将继续分享如何使用GO-ZERO进行业务开发。

通过编写API层,我们能够对外进行接口的暴露,因此学习规范的API层编写姿势是很重要的。

通过本文的分享,你将能够学习到Go-Zero的API语法规范,以及学会实际上手使用。
15 分钟前 · 北京
回复
没有更多了
Go-Zero定义API实战:探索API语法规范与最佳实践(五)_Go_王中阳Go_InfoQ写作社区