W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
前面我們介紹的命令行管理,都是通過回調(diào)函數(shù)的?parser
?對象獲取解析的參數(shù)及選項數(shù)據(jù),在使用的時候存在以下痛點(diǎn):
我們來一個最簡單的結(jié)構(gòu)化管理參數(shù)示例。我們將前面介紹過的?Command
?示例改造為結(jié)構(gòu)化管理:
package main
import (
"context"
"fmt"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/os/gctx"
)
type cMain struct {
g.Meta `name:"main"`
}
type cMainHttpInput struct {
g.Meta `name:"http" brief:"start http server"`
}
type cMainHttpOutput struct{}
type cMainGrpcInput struct {
g.Meta `name:"grpc" brief:"start grpc server"`
}
type cMainGrpcOutput struct{}
func (c *cMain) Http(ctx context.Context, in cMainHttpInput) (out *cMainHttpOutput, err error) {
fmt.Println("start http server")
return
}
func (c *cMain) Grpc(ctx context.Context, in cMainGrpcInput) (out *cMainGrpcOutput, err error) {
fmt.Println("start grpc server")
return
}
func main() {
cmd, err := gcmd.NewFromObject(cMain{})
if err != nil {
panic(err)
}
cmd.Run(gctx.New())
}
可以看到,我們通過對象的形式來管理父級命令,通過方法的形式來管理其下一層級的子級命令,并通過規(guī)范化的?Input
?輸入?yún)?shù)對象來定義子級命令的描述/參數(shù)/選項。大部分場景下,大家可以忽略?Output
?返回對象的使用,但為規(guī)范化及擴(kuò)展性需要保留,如果未用到,該返回參數(shù)直接返回?nil
?即可。關(guān)于其中的結(jié)構(gòu)體標(biāo)簽,后續(xù)會有介紹。
我們將示例代碼編譯后,執(zhí)行查看效果:
$ main
USAGE
main COMMAND [OPTION]
COMMAND
http start http server
grpc start grpc server
DESCRIPTION
this is the command entry for starting your process
使用?http
?命令:
$ main http
start http server
使用?grpc
?命令:
$ main grpc
start grpc server
效果和前面介紹的示例一致。
既然命令行通過對象化管理,我們仔細(xì)看看參數(shù)/選項是如何通過結(jié)構(gòu)化管理。
我們將上面的實例簡化一下,來個簡單的例子,實現(xiàn)通過?http
?命令開啟?http
?服務(wù):
package main
import (
"context"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/os/gctx"
)
type cMain struct {
g.Meta `name:"main" brief:"start http server"`
}
type cMainHttpInput struct {
g.Meta `name:"http" brief:"start http server"`
Name string `v:"required" name:"NAME" arg:"true" brief:"server name"`
Port int `v:"required" short:"p" name:"port" brief:"port of http server"`
}
type cMainHttpOutput struct{}
func (c *cMain) Http(ctx context.Context, in cMainHttpInput) (out *cMainHttpOutput, err error) {
s := g.Server(in.Name)
s.BindHandler("/", func(r *ghttp.Request) {
r.Response.Write("Hello world")
})
s.SetPort(in.Port)
s.Run()
return
}
func main() {
cmd, err := gcmd.NewFromObject(cMain{})
if err != nil {
panic(err)
}
cmd.Run(gctx.New())
}
我們?yōu)?http
?命令定義了兩個輸入?yún)?shù):
NAME
服務(wù)的名稱,通過參數(shù)輸入。這里使用了大寫形式,方便展示在自動生成的幫助信息中port
服務(wù)的端口,通過?p/port
?選項輸入并且我們通過?v:"required"
?校驗標(biāo)簽為這兩個參數(shù)都綁定的必需的校驗規(guī)則。是的,在?GoFrame
?框架中,只要涉及到校驗的地方都使用了統(tǒng)一的校驗組件。
我們編譯后執(zhí)行看看效果:
$ main http
arguments validation failed for command "http": The Name field is required
1. arguments validation failed for command "http"
1). github.com/gogf/gf/v2/os/gcmd.newCommandFromMethod.func1
/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/os/gcmd/gcmd_command_object.go:290
2). github.com/gogf/gf/v2/os/gcmd.(*Command).doRun
/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/os/gcmd/gcmd_command_run.go:120
3). github.com/gogf/gf/v2/os/gcmd.(*Command).RunWithValueError
/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/os/gcmd/gcmd_command_run.go:77
4). github.com/gogf/gf/v2/os/gcmd.(*Command).RunWithValue
/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/os/gcmd/gcmd_command_run.go:32
5). github.com/gogf/gf/v2/os/gcmd.(*Command).Run
/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/os/gcmd/gcmd_command_run.go:26
6). main.main
/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/.test/test.go:38
2. The Name field is required
執(zhí)行后,報錯了,這個錯誤來自于數(shù)據(jù)校驗,表示必須參數(shù)(?Name/Port
?)必須傳遞。
這里的報錯打印了堆棧信息,因為?GoFrame
?框架采用了全錯誤堆棧設(shè)計,所有組件錯誤都會帶有自底向上的錯誤堆棧,以方便錯誤快速定位。當(dāng)然我們可以通過?RunWithError
?方法獲取返回的錯誤對象關(guān)閉堆棧信息。
我們增加參數(shù)輸入再試試:
$ main http my-http-server -p 8199
2022-01-19 22:52:45.808 [DEBU] openapi specification is disabled
SERVER | DOMAIN | ADDRESS | METHOD | ROUTE | HANDLER | MIDDLEWARE
-----------------|---------|---------|--------|-------|-----------------------------------------------------------------|--------------------
my-http-server | default | :8199 | ALL | / | main.(*cMain).Http.func1 |
-----------------|---------|---------|--------|-------|-----------------------------------------------------------------|--------------------
my-http-server | default | :8199 | ALL | /* | github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing | GLOBAL MIDDLEWARE
-----------------|---------|---------|--------|-------|-----------------------------------------------------------------|--------------------
2022-01-19 22:52:45.810 66292: http server started listening on [:8199]
是的,這就對了。
?GoFrame
?框架的開發(fā)工具大量使用了對象化、結(jié)構(gòu)化的命令行管理,大家感興趣可以更進(jìn)一步查看源碼了解:https://github.com/gogf/gf-cli
在結(jié)構(gòu)化設(shè)計中,我們使用了一些結(jié)構(gòu)體標(biāo)簽,大部分來源于?Command
?命令的屬性,這里我們來介紹一下:
標(biāo)簽 | 縮寫 | 是否必須 | 說明 | 注意事項 |
?name ? |
- | 是 | 命名名稱 | |
?short ? |
- | - | 命令縮寫 | |
?usage ? |
- | - | 命令使用 | |
?brief ? |
- | - | 命令描述 | |
?age ? |
- | - | 表示該輸入?yún)?shù)來源于參數(shù)而不是選項 | 僅用于屬性標(biāo)簽 |
?orphan ? |
- | - | 表示該選項不帶參數(shù) | 屬性通常為?bool ?類型 |
?description ? |
dc | - | 命令的詳細(xì)介紹 | |
?additional ? |
ad | - | 命令的額外描述信息 | |
?examples ? |
eg | - | 命令的使用示例 | |
?root ? |
- | - | 表示統(tǒng)一結(jié)構(gòu)體方法中,該方法是父級命令,其他方法是它的子級命令 | 僅用于?Meta ?標(biāo)簽 |
?strict ? |
- | - | 表示該命令嚴(yán)格解析參數(shù)/選項,當(dāng)輸入不支持的參數(shù)/選項時,返回錯誤 | 僅用于?Meta ?標(biāo)簽
|
?config ? |
- | - | 表示該命令的選項數(shù)據(jù)支持從指定的配置讀取,配置來源于默認(rèn)的全局單例配置對象 | 僅用于?Meta ?標(biāo)簽 |
結(jié)構(gòu)化的參數(shù)輸入支持自動的數(shù)據(jù)類型轉(zhuǎn)換,您只需要定義好數(shù)據(jù)類型,其他的事情交給框架組件即可。自動數(shù)據(jù)類型轉(zhuǎn)換出現(xiàn)在框架的很多組件中,特別是?HTTP/GRPC
?服務(wù)的參數(shù)輸入中。底層數(shù)據(jù)轉(zhuǎn)換組件使用的是類型轉(zhuǎn)換
同樣的,數(shù)據(jù)校驗組件也是使用的統(tǒng)一的組件。
當(dāng)命令行中沒有傳遞對應(yīng)的數(shù)據(jù)時,輸入?yún)?shù)的結(jié)構(gòu)體數(shù)據(jù)支持從配置組件中自動獲取,只需要在?Meta
?中設(shè)置?config
?標(biāo)簽即可,配置來源于默認(rèn)的全局單例配置對象。具體示例可以參考?GoFrame
?框架開發(fā)工具源碼:https://github.com/gogf/gf-cli
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: