99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

go-zero api語法介紹

2022-04-25 17:47 更新

api示例 

/**
 * api語法示例及語法說明
 */

// api語法版本
syntax = "v1"

// import literal
import "foo.api"

// import group
import (
    "bar.api"
    "foo/bar.api"
)
info(
    author: "songmeizi"
    date:   "2020-01-08"
    desc:   "api語法示例及語法說明"
)

// type literal

type Foo{
    Foo int `json:"foo"`
}

// type group

type(
    Bar{
        Bar int `json:"bar"`
    }
)

// service block
@server(
    jwt:   Auth
    group: foo
)
service foo-api{
    @doc "foo"
    @handler foo
    post /foo (Foo) returns (Bar)
}

api語法結(jié)構(gòu)

  • syntax語法聲明
  • import語法塊
  • info語法塊
  • type語法塊
  • service語法塊
  • 隱藏通道

在以上語法結(jié)構(gòu)中,各個(gè)語法塊從語法上來說,按照語法塊為單位,可以在.api文件中任意位置聲明, 但是為了提高閱讀效率,我們建議按照以上順序進(jìn)行聲明,因?yàn)樵趯砜赡軙?huì)通過嚴(yán)格模式來控制語法塊的順序。

syntax語法聲明

?syntax?是新加入的語法結(jié)構(gòu),該語法的引入可以解決:

  • 快速針對(duì)api版本定位存在問題的語法結(jié)構(gòu)
  • 針對(duì)版本做語法解析
  • 防止api語法大版本升級(jí)導(dǎo)致前后不能向前兼容

注意

被import的api必須要和main api的syntax版本一致。

語法定義

'syntax'={checkVersion(p)}STRING

語法說明

  • ?syntax?:固定token,標(biāo)志一個(gè)syntax語法結(jié)構(gòu)的開始
  • ?checkVersion?:自定義go方法,檢測STRING是否為一個(gè)合法的版本號(hào),目前檢測邏輯為,STRING必須是滿足(?m)"v[1-9][0-9]*"正則。
  • ?STRING?:一串英文雙引號(hào)包裹的字符串,如"v1"

一個(gè)api語法文件只能有0或者1個(gè)syntax語法聲明,如果沒有syntax,則默認(rèn)為v1版本

正確語法示例

  • eg1:不規(guī)范寫法
syntax="v1"
  • eg2:規(guī)范寫法(推薦)
syntax = "v2"

錯(cuò)誤語法示例

  • eg1:
syntax = "v0"
  • eg2:
syntax = v1
  • eg3:
syntax = "V1"

import語法塊

隨著業(yè)務(wù)規(guī)模增大,api中定義的結(jié)構(gòu)體和服務(wù)越來越多,所有的語法描述均為一個(gè)api文件,這是多么糟糕的一個(gè)問題, 其會(huì)大大增加了閱讀難度和維護(hù)難度,import語法塊可以幫助我們解決這個(gè)問題,通過拆分api文件, 不同的api文件按照一定規(guī)則聲明,可以降低閱讀難度和維護(hù)難度。

注意

這里import不像golang那樣包含package聲明,僅僅是一個(gè)文件路徑的引入,最終解析后會(huì)把所有的聲明都匯聚到一個(gè)spec.Spec中。 不能import多個(gè)相同路徑,否則會(huì)解析錯(cuò)誤。

語法定義

'import' {checkImportValue(p)}STRING  
|'import' '(' ({checkImportValue(p)}STRING)+ ')'

語法說明

  • ?import?:固定token,標(biāo)志一個(gè)import語法的開始
  • ?checkImportValue?:自定義go方法,檢測STRING是否為一個(gè)合法的文件路徑,目前檢測邏輯為,STRING必須是滿足(?m)"(/?[a-zA-Z0-9_#-])+\.api"正則。
  • ?STRING?:一串英文雙引號(hào)包裹的字符串,如"foo.api"

正確語法示例

  • eg:
import "foo.api"
import "foo/bar.api"

import(
    "bar.api"
    "foo/bar/foo.api"
)

錯(cuò)誤語法示例

  • eg:
import foo.api
import "foo.txt"
import (
    bar.api
    bar.api
)

info語法塊

info語法塊是一個(gè)包含了多個(gè)鍵值對(duì)的語法體,其作用相當(dāng)于一個(gè)api服務(wù)的描述,解析器會(huì)將其映射到spec.Spec中, 以備用于翻譯成其他語言(golang、java等) 時(shí)需要攜帶的meta元素。如果僅僅是對(duì)當(dāng)前api的一個(gè)說明,而不考慮其翻譯 時(shí)傳遞到其他語言,則使用簡單的多行注釋或者java風(fēng)格的文檔注釋即可,關(guān)于注釋說明請(qǐng)參考下文的 隱藏通道。

注意
不能使用重復(fù)的key,每個(gè)api文件只能有0或者1個(gè)info語法塊

語法定義

'info' '(' (ID {checkKeyValue(p)}VALUE)+ ')'

語法說明

  • ?info?:固定token,標(biāo)志一個(gè)info語法塊的開始
  • ?checkKeyValue?:自定義go方法,檢測VALUE是否為一個(gè)合法值。
  • ?VALUE?:key對(duì)應(yīng)的值,可以為單行的除'\r','\n','/'后的任意字符,多行請(qǐng)以""包裹,不過強(qiáng)烈建議所有都以""包裹

正確語法示例

  • eg1:不規(guī)范寫法
info(
foo: foo value
bar:"bar value"
    desc:"long long long long
long long text"
)
  • eg2:規(guī)范寫法(推薦)
info(
    foo: "foo value"
    bar: "bar value"
    desc: "long long long long long long text"
)

錯(cuò)誤語法示例

  • eg1:沒有key-value內(nèi)容
info()
  • eg2:不包含冒號(hào)
info(
    foo value
)
  • eg3:key-value沒有換行
info(foo:"value")
  • eg4:沒有key
info(
    : "value"
)
  • eg5:非法的key
info(
    12: "value"
)
  • eg6:移除舊版本多行語法
info(
    foo: >
    some text
    <
)

type語法塊

在api服務(wù)中,我們需要用到一個(gè)結(jié)構(gòu)體(類)來作為請(qǐng)求體,響應(yīng)體的載體,因此我們需要聲明一些結(jié)構(gòu)體來完成這件事情, type語法塊由golang的type演變而來,當(dāng)然也保留著一些golang type的特性,沿用golang特性有:

  • 保留了golang內(nèi)置數(shù)據(jù)類型?bool?,?int?,?int8?,?int16?,?int32?,?int64?,?uint?,?uint8?,?uint16?,?uint32?,?uint64?,?uintptr ?,?float32?,?float64?,?complex64?,?complex128?,?string?,?byte?,?rune?,
  • 兼容golang struct風(fēng)格聲明
  • 保留golang關(guān)鍵字
注意
  • 不支持alias
  • 不支持time.Time數(shù)據(jù)類型
  • 結(jié)構(gòu)體名稱、字段名稱、不能為golang關(guān)鍵字

語法定義

由于其和golang相似,因此不做詳細(xì)說明,具體語法定義請(qǐng)?jiān)?nbsp;ApiParser.g4 中查看typeSpec定義。

語法說明

參考golang寫法

正確語法示例

  • eg1:不規(guī)范寫法
type Foo struct{
    Id int `path:"id"` // ①
    Foo int `json:"foo"`
}

type Bar struct{
    // 非導(dǎo)出型字段
    bar int `form:"bar"`
}

type(
    // 非導(dǎo)出型結(jié)構(gòu)體
    fooBar struct{
        FooBar int `json:"fooBar"`
    }
)
  • eg2:規(guī)范寫法(推薦)
type Foo{
    Id int `path:"id"`
    Foo int `json:"foo"`
}

type Bar{
    Bar int `form:"bar"`
}

type(
    FooBar{
        FooBar int `json:"fooBar"`
    }
)

錯(cuò)誤語法示例

  • eg
type Gender int // 不支持

// 非struct token
type Foo structure{ 
  CreateTime time.Time // 不支持time.Time,且沒有聲明 tag
}

// golang關(guān)鍵字 var
type var{} 

type Foo{
  // golang關(guān)鍵字 interface
  Foo interface  // 沒有聲明 tag
}


type Foo{
  foo int 
  // map key必須要golang內(nèi)置數(shù)據(jù)類型,且沒有聲明 tag
  m map[Bar]string
}

 tag定義和golang中json tag語法一樣,除了json tag外,go-zero還提供了另外一些tag來實(shí)現(xiàn)對(duì)字段的描述, 詳情見下表。

  • tag表

綁定參數(shù)時(shí),以下四個(gè)tag只能選擇其中一個(gè)

tag key 描述 提供方 有效范圍 示例
json json序列化tag golang request、response json:"fooo"
path 路由path,如/foo/:id go-zero request path:"id"
form 標(biāo)志請(qǐng)求體是一個(gè)form(POST方法時(shí))或者一個(gè)query(GET方法時(shí)/search?name=keyword) go-zero request form:"name"
header HTTP header,如 Name: value go-zero request header:"name"
  • tag修飾符

常見參數(shù)校驗(yàn)描述

tag key 描述 提供方 有效范圍 示例
optional 定義當(dāng)前字段為可選參數(shù) go-zero request json:"name,optional"
options 定義當(dāng)前字段的枚舉值,多個(gè)以豎線|隔開 go-zero request json:"gender,options=male"
default 定義當(dāng)前字段默認(rèn)值 go-zero request json:"gender,default=male"
range 定義當(dāng)前字段數(shù)值范圍 go-zero request json:"age,range=[0:120]"
Tip
tag修飾符需要在tag value后以英文逗號(hào),隔開

service語法塊

service語法塊用于定義api服務(wù),包含服務(wù)名稱,服務(wù)metadata,中間件聲明,路由,handler等。

注意
  • main api和被import的api服務(wù)名稱必須一致,不能出現(xiàn)服務(wù)名稱歧義。
  • handler名稱不能重復(fù)
  • 路由(請(qǐng)求方法+請(qǐng)求path)名稱不能重復(fù)
  • 請(qǐng)求體必須聲明為普通(非指針)struct,響應(yīng)體做了一些向前兼容處理,詳請(qǐng)見下文說明

語法定義

serviceSpec:    atServer? serviceApi;
atServer:       '@server' lp='(' kvLit+ rp=')';
serviceApi:     {match(p,"service")}serviceToken=ID serviceName lbrace='{' serviceRoute* rbrace='}';
serviceRoute:   atDoc? (atServer|atHandler) route;
atDoc:          '@doc' lp='('? ((kvLit+)|STRING) rp=')'?;
atHandler:      '@handler' ID;
route:          {checkHttpMethod(p)}httpMethod=ID path request=body? returnToken=ID? response=replybody?;
body:           lp='(' (ID)? rp=')';
replybody:      lp='(' dataType? rp=')';
// kv
kvLit:          key=ID {checkKeyValue(p)}value=LINE_VALUE;

serviceName:    (ID '-'?)+;
path:           (('/' (ID ('-' ID)*))|('/:' (ID ('-' ID)?)))+;

語法說明

  • ?serviceSpec?:包含了一個(gè)可選語法塊atServer和serviceApi語法塊,其遵循序列模式(編寫service必須要按照順序,否則會(huì)解析出錯(cuò))
  • ?atServer?: 可選語法塊,定義key-value結(jié)構(gòu)的server metadata,'@server' 表示這一個(gè)server語法塊的開始,其可以用于描述serviceApi或者route語法塊,其用于描述不同語法塊時(shí)有一些特殊關(guān)鍵key 需要值得注意,見 atServer關(guān)鍵key描述說明。
  • ?serviceApi?:包含了1到多個(gè)serviceRoute語法塊
  • ?serviceRoute?:按照序列模式包含了atDoc,handler和route
  • ?atDoc?:可選語法塊,一個(gè)路由的key-value描述,其在解析后會(huì)傳遞到spec.Spec結(jié)構(gòu)體,如果不關(guān)心傳遞到spec.Spec, 推薦用單行注釋替代。
  • ?handler?:是對(duì)路由的handler層描述,可以通過atServer指定handler key來指定handler名稱, 也可以直接用atHandler語法塊來定義handler名稱
  • ?atHandler?:'@handler' 固定token,后接一個(gè)遵循正則[_a-zA-Z][a-zA-Z_-]*)的值,用于聲明一個(gè)handler名稱
  • ?route?:路由,有httpMethod、path、可選request、可選response組成,httpMethod是必須是小寫。
  • ?body?:api請(qǐng)求體語法定義,必須要由()包裹的可選的ID值
  • ?replyBody?:api響應(yīng)體語法定義,必須由()包裹的struct、array(向前兼容處理,后續(xù)可能會(huì)廢棄,強(qiáng)烈推薦以struct包裹,不要直接用array作為響應(yīng)體)
  • ?kvLit?: 同info key-value
  • ?serviceName?: 可以有多個(gè)'-'join的ID值
  • ?path?:api請(qǐng)求路徑,必須以'/'或者'/:'開頭,切不能以'/'結(jié)尾,中間可包含ID或者多個(gè)以'-'join的ID字符串

atServer關(guān)鍵key描述說明

  • 修飾service時(shí)
key 描述 示例
jwt 聲明當(dāng)前service下所有路由需要jwt鑒權(quán),且會(huì)自動(dòng)生成包含jwt邏輯的代碼 jwt: Auth
group 聲明當(dāng)前service或者路由文件分組 group: login
middleware 聲明當(dāng)前service需要開啟中間件 middleware: AuthMiddleware
prefix 添加路由分組 prefix: api
  • 修飾route時(shí)
key 描述 示例
handler 聲明一個(gè)handler -

正確語法示例

  • eg1:不規(guī)范寫法
@server(
  jwt: Auth
  group: foo
  middleware: AuthMiddleware
  prefix api
)
service foo-api{
  @doc(
    summary: foo
  )
  @server(
    handler: foo
  )
  // 非導(dǎo)出型body
  post /foo/:id (foo) returns (bar)

  @doc "bar"
  @handler bar
  post /bar returns ([]int)// 不推薦數(shù)組作為響應(yīng)體

  @handler fooBar
  post /foo/bar (Foo) returns // 可以省略'returns'
}
  • eg2:規(guī)范寫法(推薦)
@server(
  jwt: Auth
  group: foo
  middleware: AuthMiddleware
  prefix: api
)
service foo-api{
  @doc "foo"
  @handler foo
  post /foo/:id (Foo) returns (Bar)
}

service foo-api{
  @handler ping
  get /ping

  @doc "foo"
  @handler bar
  post /bar/:id (Foo)
}

錯(cuò)誤語法示例

// 不支持空的server語法塊
@server(
)
// 不支持空的service語法塊
service foo-api{
}

service foo-api{
  @doc kkkk // 簡版doc必須用英文雙引號(hào)引起來
  @handler foo
  post /foo

  @handler foo // 重復(fù)的handler
  post /bar

  @handler fooBar
  post /bar // 重復(fù)的路由

  // @handler和@doc順序錯(cuò)誤
  @handler someHandler
  @doc "some doc"
  post /some/path

  // handler缺失
  post /some/path/:id

  @handler reqTest
  post /foo/req (*Foo) // 不支持除普通結(jié)構(gòu)體外的其他數(shù)據(jù)類型作為請(qǐng)求體

  @handler replyTest
  post /foo/reply returns (*Foo) // 不支持除普通結(jié)構(gòu)體、數(shù)組(向前兼容,后續(xù)考慮廢棄)外的其他數(shù)據(jù)類型作為響應(yīng)體
}

隱藏通道

隱藏通道目前主要為空白符號(hào)、換行符號(hào)以及注釋,這里我們只說注釋,因?yàn)榭瞻追?hào)和換行符號(hào)我們目前拿來也無用。

單行注釋

語法定義
'//' ~[\r\n]*
語法說明 

由語法定義可知道,單行注釋必須要以//開頭,內(nèi)容為不能包含換行符

正確語法示例
// doc
// comment
錯(cuò)誤語法示例
// break
line comments

java風(fēng)格文檔注釋

語法定義
'/*' .*? '*/'
語法說明

由語法定義可知道,單行注釋必須要以/*開頭,*/結(jié)尾的任意字符。

正確語法示例
/**
 * java-style doc
 */
錯(cuò)誤語法示例
/*
 * java-style doc */
 */

Doc&Comment

如果想獲取某一個(gè)元素的doc或者comment開發(fā)人員需要怎么定義?

Doc

我們規(guī)定上一個(gè)語法塊(非隱藏通道內(nèi)容)的行數(shù)line+1到當(dāng)前語法塊第一個(gè)元素前的所有注釋(單行,或者多行)均為doc, 且保留了//、/*、*/原始標(biāo)記。

Comment

我們規(guī)定當(dāng)前語法塊最后一個(gè)元素所在行開始的一個(gè)注釋塊(當(dāng)行,或者多行)為comment 且保留了//、/*、*/原始標(biāo)記。 語法塊Doc和Comment的支持情況

語法塊 parent語法塊 Doc Comment
syntaxLit api ? ?
kvLit infoSpec ? ?
importLit importSpec ? ?
typeLit api ? ?
typeLit typeBlock ? ?
field typeLit ? ?
key-value atServer ? ?
atHandler serviceRoute ? ?
route serviceRoute ? ?

以下為對(duì)應(yīng)語法塊解析后細(xì)帶doc和comment的寫法

// syntaxLit doc
syntax = "v1" // syntaxLit commnet

info(
  // kvLit doc
  author: songmeizi // kvLit comment
)

// typeLit doc
type Foo {}

type(
  // typeLit doc
  Bar{}

  FooBar{
    // filed doc
    Name int // filed comment
  }
)

@server(
  /**
   * kvLit doc
   * 開啟jwt鑒權(quán)
   */
  jwt: Auth /**kvLit comment*/
)
service foo-api{
  // atHandler doc
  @handler foo //atHandler comment

  /*
   * route doc
   * post請(qǐng)求
   * path為 /foo
   * 請(qǐng)求體:Foo
   * 響應(yīng)體:Foo
   */
  post /foo (Foo) returns (Foo) // route comment
}


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)