api 语法

api 语法

概述

api 是 go-zero 自研的领域特性语言(下文称 api 语言 或 api 描述语言),旨在实现人性化的基础描述语言,作为生成 HTTP 服务最基本的描述语言。

api 领域特性语言包含语法版本,info 块,结构体声明,服务描述等几大块语法组成,其中结构体和 Golang 结构体 语法几乎一样,只是移出了 struct 关键字。

快速入门

本次仅以 demo 形式快速介绍 api 文件的写法,更详细的写法示例可参考 《API 定义完整示例》,详细 api 语法规范可参考 《API 规范》。

示例 1. 编写最简单的 ping 路由服务

syntax = "v1"

// 定义 HTTP 服务
service foo {
    get /ping
}

示例 2. 编写一个登录接口 api 文件

syntax = "v1"

type (
    // 定义登录接口的请求体
    LoginReq {
        Username string `json:"username"`
        Password string `json:"password"`
    }
    // 定义登录接口的响应体
    LoginResp {
        Id       int64  `json:"id"`
        Name     string `json:"name"`
        Token    string `json:"token"`
        ExpireAt string `json:"expireAt"`
    }
)

// 定义 HTTP 服务
// 微服务名称为 user,生成的代码目录和配置文件将和 user 值相关
service user {
    // 定义 http.HandleFunc 转换的 go 文件名称及方法
    @handler Login
    // 定义接口
    // 请求方法为 post
    // 路由为 /user/login
    // 请求体为 LoginReq
    // 响应体为 LoginResp,响应体必须有 returns 关键字修饰
    post /user/login (LoginReq) returns (LoginResp)
}

示例 3. 编写简单的用户服务 api 文件

syntax = "v1"

type (
    // 定义登录接口的 json 请求体
    LoginReq {
        Username string `json:"username"`
        Password string `json:"password"`
    }
    // 定义登录接口的 json 响应体
    LoginResp {
        Id       int64  `json:"id"`
        Name     string `json:"name"`
        Token    string `json:"token"`
        ExpireAt string `json:"expireAt"`
    }
)

type (
    // 定义获取用户信息的 json 请求体
    GetUserInfoReq {
        Id int64 `json:"id"`
    }
    // 定义获取用户信息的 json 响应体
    GetUserInfoResp {
        Id   int64  `json:"id"`
        Name string `json:"name"`
        Desc string `json:"desc"`
    }
    // 定义更新用户信息的 json 请求体
    UpdateUserInfoReq {
        Id   int64  `json:"id"`
        Name string `json:"name"`
        Desc string `json:"desc"`
    }
)

// 定义 HTTP 服务
// @server 语法块主要用于控制对 HTTP 服务生成时 meta 信息,目前支持功能有:
// 1. 路由分组
// 2. 中间件声明
// 3. 路由前缀
// 4. 超时配置
// 5. jwt 鉴权开关
// 所有声明仅对当前 service 中的路由有效
@server (
    // 代表当前 service 代码块下的路由生成代码时都会被放到 login 目录下
    group: login
    // 定义路由前缀为 "/v1"
    prefix: /v1
)
// 微服务名称为 user,生成的代码目录和配置文件将和 user 值相关
service user {
    // 定义 http.HandleFunc 转换的 go 文件名称及方法,每个接口都会跟一个 handler
    @handler login
    // 定义接口
    // 请求方法为 post
    // 路由为 /user/login
    // 请求体为 LoginReq
    // 响应体为 LoginResp,响应体必须有 returns 关键字修饰
    post /user/login (LoginReq) returns (LoginResp)
}

// @server 语法块主要用于控制对 HTTP 服务生成时 meta 信息,目前支持功能有:
// 1. 路由分组
// 2. 中间件声明
// 3. 路由前缀
// 4. 超时配置
// 5. jwt 鉴权开关
// 所有声明仅对当前 service 中的路由有效
@server (
    // 代表当前 service 代码块下的所有路由均需要 jwt 鉴权
    // goctl 生成代码时会将当前 service 代码块下的接口
    // 信息添加上 jwt 相关代码,Auth 值为 jwt 密钥,过期
    // 等信息配置的 golang 结构体名称
    jwt: Auth
    // 代表当前 service 代码块下的路由生成代码时都会被放到 user 目录下
    group: user
    // 定义路由前缀为 "/v1"
    prefix: /v1
)
// 注意,定义多个 service 代码块时,服务名称必须一致,因此这里的服务名称必须
// 和上文的 service 名称一样,为 user 服务。
service user {
    // 定义 http.HandleFunc 转换的 go 文件名称及方法,每个接口都会跟一个 handler
    @handler getUserInfo
    // 定义接口
    // 请求方法为 post
    // 路由为 /user/info
    // 请求体为 GetUserInfoReq
    // 响应体为 GetUserInfoResp,响应体必须有 returns 关键字修饰
    post /user/info (GetUserInfoReq) returns (GetUserInfoResp)

    // 定义 http.HandleFunc 转换的 go 文件名称及方法,每个接口都会跟一个 handler
    @handler updateUserInfo
    // 定义接口
    // 请求方法为 post
    // 路由为 /user/info/update
    // 请求体为 UpdateUserInfoReq
    // 由于不需要响应体,因此可以忽略不写
    post /user/info/update (UpdateUserInfoReq)
}

示例 4. 编写带有中间件的 api 服务

syntax = "v1"

type GetUserInfoReq {
    Id int64 `json:"id"`
}

type GetUserInfoResp {
    Id   int64  `json:"id"`
    Name string `json:"name"`
    Desc string `json:"desc"`
}

// @server 语法块主要用于控制对 HTTP 服务生成时 meta 信息,目前支持功能有:
// 1. 路由分组
// 2. 中间件声明
// 3. 路由前缀
// 4. 超时配置
// 5. jwt 鉴权开关
// 所有声明仅对当前 service 中的路由有效
@server (
    // 定义一个鉴权控制的中间件,多个中间件以英文逗号,分割,如 Middleware1,Middleware2,中间件按声明顺序执行
    middleware: AuthInterceptor
)
// 定义一个名称为 user 的服务
service user {
    // 定义 http.HandleFunc 转换的 go 文件名称及方法,每个接口都会跟一个 handler
    @handler getUserInfo
    // 定义接口
    // 请求方法为 post
    // 路由为 /user/info
    // 请求体为 GetUserInfoReq
    // 响应体为 GetUserInfoResp,响应体必须有 returns 关键字修饰
    post /user/info (GetUserInfoReq) returns (GetUserInfoResp)
}

示例 5. 编写带有超时配置的 api 服务

syntax = "v1"

type GetUserInfoReq {
    Id int64 `json:"id"`
}

type GetUserInfoResp {
    Id   int64  `json:"id"`
    Name string `json:"name"`
    Desc string `json:"desc"`
}

// @server 语法块主要用于控制对 HTTP 服务生成时 meta 信息,目前支持功能有:
// 1. 路由分组
// 2. 中间件声明
// 3. 路由前缀
// 4. 超时配置
// 5. jwt 鉴权开关
// 所有声明仅对当前 service 中的路由有效
@server (
    // 定义一个超时时长为 3 秒的超时配置,这里可填写为 time.Duration 的字符串形式,详情可参考
    // https://pkg.go.dev/time#Duration.String
    timeout: 3s
)
// 定义一个名称为 user 的服务
service user {
    // 定义 http.HandleFunc 转换的 go 文件名称及方法,每个接口都会跟一个 handler
    @handler getUserInfo
    // 定义接口
    // 请求方法为 post
    // 路由为 /user/info
    // 请求体为 GetUserInfoReq
    // 响应体为 GetUserInfoResp,响应体必须有 returns 关键字修饰
    post /user/info (GetUserInfoReq) returns (GetUserInfoResp)
}

示例 6. 结构体引用

syntax = "v1"

type Base {
    Code int    `json:"code"`
    Msg  string `json:"msg"`
}

type UserInfo {
    Id   int64  `json:"id"`
    Name string `json:"name"`
    Desc string `json:"desc"`
}

type GetUserInfoReq {
    Id int64 `json:"id"`
}

type GetUserInfoResp {
    // api 支持匿名结构体嵌套,也支持结构体引用
    Base
    Data UserInfo `json:"data"`
    // 匿名结构体
    Nested {
      Foo string `json:"foo"`
    } `json:"nested"`
}

// 定义一个名称为 user 的服务
service user {
    // 定义 http.HandleFunc 转换的 go 文件名称及方法,每个接口都会跟一个 handler
    @handler getUserInfo
    // 定义接口
    // 请求方法为 post
    // 路由为 /user/info
    // 请求体为 GetUserInfoReq
    // 响应体为 GetUserInfoResp,响应体必须有 returns 关键字修饰
    post /user/info (GetUserInfoReq) returns (GetUserInfoResp)
}

示例 7. 控制最大请求体控制的 api 服务

syntax = "v1"

type GetUserInfoReq {
    Id int64 `json:"id"`
}

type GetUserInfoResp {
    Id   int64  `json:"id"`
    Name string `json:"name"`
    Desc string `json:"desc"`
}

// @server 语法块主要用于控制对 HTTP 服务生成时 meta 信息,目前支持功能有:
// 1. 路由分组
// 2. 中间件声明
// 3. 路由前缀
// 4. 超时配置
// 5. jwt 鉴权开关
// 所有声明仅对当前 service 中的路由有效
@server (
    // 定义一个请求体限制在 1MB 以内的请求,goctl >= 1.5.0 版本支持
    maxBytes: 1048576
)
// 定义一个名称为 user 的服务
service user {
    // 定义 http.HandleFunc 转换的 go 文件名称及方法,每个接口都会跟一个 handler
    @handler getUserInfo
    // 定义接口
    // 请求方法为 post
    // 路由为 /user/info
    // 请求体为 GetUserInfoReq
    // 响应体为 GetUserInfoResp,响应体必须有 returns 关键字修饰
    post /user/info (GetUserInfoReq) returns (GetUserInfoResp)
}

参考文献