日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
創(chuàng)新互聯(lián)GoFrame教程:GoFrame命令管理-結(jié)構(gòu)化參數(shù)

命令行管理痛點(diǎn)

前面我們介紹的命令行管理,都是通過(guò)回調(diào)函數(shù)的?parser?對(duì)象獲取解析的參數(shù)及選項(xiàng)數(shù)據(jù),在使用的時(shí)候存在以下痛點(diǎn):

目前成都創(chuàng)新互聯(lián)公司已為1000多家的企業(yè)提供了網(wǎng)站建設(shè)、域名、雅安服務(wù)器托管、網(wǎng)站托管、服務(wù)器租用、企業(yè)網(wǎng)站設(shè)計(jì)、嘉祥網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。

  • 需要手動(dòng)傳入硬編碼的參數(shù)索引或者選項(xiàng)名稱(chēng)信息來(lái)獲取數(shù)據(jù)
  • 難以定義參數(shù)/選項(xiàng)的說(shuō)明介紹
  • 難以定義參數(shù)/選項(xiàng)的數(shù)據(jù)類(lèi)型
  • 難以對(duì)參數(shù)/選項(xiàng)進(jìn)行數(shù)據(jù)校驗(yàn)
  • 對(duì)于需要管理大量命令行的項(xiàng)目是個(gè)災(zāi)難

對(duì)象化管理命令

我們來(lái)一個(gè)最簡(jiǎn)單的結(jié)構(gòu)化管理參數(shù)示例。我們將前面介紹過(guò)的?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ò)對(duì)象的形式來(lái)管理父級(jí)命令,通過(guò)方法的形式來(lái)管理其下一層級(jí)的子級(jí)命令,并通過(guò)規(guī)范化的?Input?輸入?yún)?shù)對(duì)象來(lái)定義子級(jí)命令的描述/參數(shù)/選項(xiàng)。大部分場(chǎng)景下,大家可以忽略?Output?返回對(duì)象的使用,但為規(guī)范化及擴(kuò)展性需要保留,如果未用到,該返回參數(shù)直接返回?nil?即可。關(guān)于其中的結(jié)構(gòu)體標(biāo)簽,后續(xù)會(huì)有介紹。

我們將示例代碼編譯后,執(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

效果和前面介紹的示例一致。

結(jié)構(gòu)化管理入?yún)?

既然命令行通過(guò)對(duì)象化管理,我們仔細(xì)看看參數(shù)/選項(xiàng)是如何通過(guò)結(jié)構(gòu)化管理。

我們將上面的實(shí)例簡(jiǎn)化一下,來(lái)個(gè)簡(jiǎn)單的例子,實(shí)現(xiàn)通過(guò)?http?命令開(kāi)啟?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?命令定義了兩個(gè)輸入?yún)?shù):

  • ?NAME服務(wù)的名稱(chēng),通過(guò)參數(shù)輸入。這里使用了大寫(xiě)形式,方便展示在自動(dòng)生成的幫助信息中
  • ?port服務(wù)的端口,通過(guò)?p/port?選項(xiàng)輸入

并且我們通過(guò)?v:"required"?校驗(yàn)標(biāo)簽為這兩個(gè)參數(shù)都綁定的必需的校驗(yàn)規(guī)則。是的,在?GoFrame?框架中,只要涉及到校驗(yàn)的地方都使用了統(tǒng)一的校驗(yàn)組件。

我們編譯后執(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í)行后,報(bào)錯(cuò)了,這個(gè)錯(cuò)誤來(lái)自于數(shù)據(jù)校驗(yàn),表示必須參數(shù)(?Name/Port?)必須傳遞。

這里的報(bào)錯(cuò)打印了堆棧信息,因?yàn)?GoFrame?框架采用了全錯(cuò)誤堆棧設(shè)計(jì),所有組件錯(cuò)誤都會(huì)帶有自底向上的錯(cuò)誤堆棧,以方便錯(cuò)誤快速定位。當(dāng)然我們可以通過(guò)?RunWithError?方法獲取返回的錯(cuò)誤對(duì)象關(guān)閉堆棧信息。

我們?cè)黾訁?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] 

是的,這就對(duì)了。

完整使用案例

?GoFrame?框架的開(kāi)發(fā)工具大量使用了對(duì)象化、結(jié)構(gòu)化的命令行管理,大家感興趣可以更進(jìn)一步查看源碼了解:https://github.com/gogf/gf-cli

預(yù)定義的標(biāo)簽

在結(jié)構(gòu)化設(shè)計(jì)中,我們使用了一些結(jié)構(gòu)體標(biāo)簽,大部分來(lái)源于?Command?命令的屬性,這里我們來(lái)介紹一下:

 標(biāo)簽  縮寫(xiě)  是否必須  說(shuō)明  注意事項(xiàng)
 ?name?  -  是  命名名稱(chēng)  
 ?short?  -  -  命令縮寫(xiě)  
 ?usage?  -  -  命令使用  
 ?brief?  -  -  命令描述  
 ?age?  -  -  表示該輸入?yún)?shù)來(lái)源于參數(shù)而不是選項(xiàng)  僅用于屬性標(biāo)簽
 ?orphan?  -  -  表示該選項(xiàng)不帶參數(shù)  屬性通常為?bool?類(lèi)型
 ?description?  dc  -  命令的詳細(xì)介紹  
 ?additional?  ad  -  命令的額外描述信息  
 ?examples?  eg  -  命令的使用示例  
 ?root?  -  -  表示統(tǒng)一結(jié)構(gòu)體方法中,該方法是父級(jí)命令,其他方法是它的子級(jí)命令  僅用于?Meta?標(biāo)簽
 ?strict?  -  -  表示該命令嚴(yán)格解析參數(shù)/選項(xiàng),當(dāng)輸入不支持的參數(shù)/選項(xiàng)時(shí),返回錯(cuò)誤  僅用于?Meta?標(biāo)簽
 ?config?  -  -  表示該命令的選項(xiàng)數(shù)據(jù)支持從指定的配置讀取,配置來(lái)源于默認(rèn)的全局單例配置對(duì)象  僅用于?Meta?標(biāo)簽

高級(jí)特性

自動(dòng)數(shù)據(jù)轉(zhuǎn)換

結(jié)構(gòu)化的參數(shù)輸入支持自動(dòng)的數(shù)據(jù)類(lèi)型轉(zhuǎn)換,您只需要定義好數(shù)據(jù)類(lèi)型,其他的事情交給框架組件即可。自動(dòng)數(shù)據(jù)類(lèi)型轉(zhuǎn)換出現(xiàn)在框架的很多組件中,特別是?HTTP/GRPC?服務(wù)的參數(shù)輸入中。底層數(shù)據(jù)轉(zhuǎn)換組件使用的是類(lèi)型轉(zhuǎn)換

自動(dòng)數(shù)據(jù)校驗(yàn)

同樣的,數(shù)據(jù)校驗(yàn)組件也是使用的統(tǒng)一的組件。

從配置讀取數(shù)據(jù)

當(dāng)命令行中沒(méi)有傳遞對(duì)應(yīng)的數(shù)據(jù)時(shí),輸入?yún)?shù)的結(jié)構(gòu)體數(shù)據(jù)支持從配置組件中自動(dòng)獲取,只需要在?Meta?中設(shè)置?config?標(biāo)簽即可,配置來(lái)源于默認(rèn)的全局單例配置對(duì)象。具體示例可以參考?GoFrame?框架開(kāi)發(fā)工具源碼:https://github.com/gogf/gf-cli


網(wǎng)站名稱(chēng):創(chuàng)新互聯(lián)GoFrame教程:GoFrame命令管理-結(jié)構(gòu)化參數(shù)
標(biāo)題網(wǎng)址:http://www.dlmjj.cn/article/dphcscg.html