『如何構(gòu)建命令行工具:YiYi』

封面.png

大家好过牙,我是謝偉甥厦,是一名程序員。

過去一陣子寇钉,我在開發(fā)一款客戶端命令行工具刀疙,業(yè)余時間,開始寫了下面這個工具扫倡。僅做學習參考使用∏恚現(xiàn)在它看上去不夠優(yōu)雅,命令的命名也沒有好好推敲撵溃。但功能都已實現(xiàn)油够。

即如何構(gòu)建一個命令行工具,希望通過這個項目的示例征懈,你能開發(fā)出各種各樣符合你需求的命令行工具。

比如 github 上非常熱門的命令行項目:

  • annie 下載視頻和圖片工具
  • hub 一個包裝git 操作github 的工具
  • jfrog-cli-go 一個倉庫管理平臺的客戶端

...

開始之前揩悄,還是看幾個命令行工具一般是啥樣的:

beego: 命令行工具bee


λ bee
Bee is a Fast and Flexible tool for managing your Beego Web Application.

USAGE
    bee command [arguments]

AVAILABLE COMMANDS

    version     Prints the current Bee version
    migrate     Runs database migrations
    api         Creates a Beego API application
    bale        Transforms non-Go files to Go source files
    fix         Fixes your application by making it compatible with newer versions of Beego
    dlv         Start a debugging session using Delve
    dockerize   Generates a Dockerfile for your Beego application
    generate    Source code generator
    hprose      Creates an RPC application based on Hprose and Beego frameworks
    new         Creates a Beego application
    pack        Compresses a Beego application into a single file
    rs          Run customized scripts
    run         Run the application by starting a local development server
    server      serving static content over HTTP on port

Use bee help [command] for more information about a command.

ADDITIONAL HELP TOPICS


Use bee help [topic] for more information about that topic.

思考一個問題:一個好的命令行應該具備什么卖哎?

  • 完善的幫助命令
  • 優(yōu)雅的輸出格式
  • 支持長、短參數(shù)
  • 命令補全
  • 支持表格輸出

等等

實質(zhì):客戶端命令行工具的實質(zhì)是 接口或者API 的封裝删性。

1亏娜、如何解析命令行參數(shù)

  • os.Args
  • Flag
  • cli

1. os.Args:

第一個參數(shù)是: 文件名稱,之外的參數(shù)是命令行接收的參數(shù)

對參數(shù)進行處理即可實現(xiàn)解析命令行參數(shù)蹬挺。

args = os.Args

oneArg = args[1]

TwoArg = args[2]

func add() int {
    number_one, _ := strconv.Atoi(args[2])
    number_two, _ := strconv.Atoi(args[3])
    return number_one + number_two
}

2. Flag

Flag golang 系統(tǒng)自帶的庫能更好的處理命令行參數(shù):

    var operation string
    var numberone float64
    var numbertwo float64
    flag.StringVar(&operation, "o", "add", "operation for this tool")
    flag.Float64Var(&numberone, "n1", 0, "The first number")
    flag.Float64Var(&numbertwo, "n2", 0, "The second number")


定義三個參數(shù)维贺,分別為string、float巴帮、float 類型

3. cli

這是一個第三方庫溯泣,是一個命令參數(shù)解析的框架,能夠很好的快速形成命令行榕茧。

cli項目地址

主要包括:

  • app 主要實現(xiàn)的是整體的命令行工具動作
  • command 對命令的處理
  • flag 對短參數(shù)的處理
  • help 使用 template 模板實現(xiàn)命令的幫助提示

2垃沦、如何組織項目

  • commands : 命令集合
  • domain: http 請求處理
  • main: 程序入口
  • objects: 定義結(jié)構(gòu)體
  • reader : 命令清單入口
  • utils: 程序幫助程序入口

3、如何組織命令

第一級命令集合

func Commands() []cli.Command {
    return []cli.Command{
        {
            Name:        "book",
            Usage:       douban.BookUsage,
            Subcommands: douban.SubBookCommand(),
        },
        {
            Name:        "story",
            Usage:       one.StoryUsage,
            Subcommands: one.SubStoryCommand(),
        },
        {
            Name:        "movie",
            Usage:       douban.MovieUsage,
            Subcommands: douban.SubMovieCommand(),
        },
    }
}

第二級命令集合:

func SubBookCommand() []cli.Command {
    return []cli.Command{
        {
            Name:   "random",
            Action: actionBookNumber,
        },
        {
            Name:   "detail",
            Action: actionBookDetail,
        },
        {
            Name:        "search",
            Flags:       getFlagSearch(),
            Subcommands: subCommandBookSearch(),
        },
    }
}

第三級命令集合:

func subCommandBookSearch() []cli.Command {
    return []cli.Command{
        {
            Name:   "query",
            Action: actionQuery,
        },
        {
            Name:   "tag",
            Action: actionTag,
        },
    }
}

組合起來即是: YiYi.exe book random | detail | search query | search tag ...

可以看出該框架對命令的組織方式很優(yōu)雅用押≈荆可以讓使用者聚焦在實現(xiàn)業(yè)務上。

4、操作步驟

YiYi.png
  • 組織命令
  • 實現(xiàn)具體函數(shù)處理

這里以:YiYi.exe book search query arg 這個命令講述如何實現(xiàn)池充。

實例化APP


func main(){
    app := cli.NewApp()
    app.CommandNotFound = func(context *cli.Context, command string) {
        fmt.Printf("[[WARNING] Not Found Command: %s\n", command)
        fmt.Printf("[MESSAGE] Please Type: Reader --help")
    }
    app.Commands = reader.Commands()
    app.Run(os.Args)
}

定義Commands


func Commands() []cli.Command {
    return []cli.Command{
        {
            Name:        "book",
            Usage:       douban.BookUsage,
            Subcommands: douban.SubBookCommand(),
        },

    }
}

定義 SubCommand

func SubBookCommand() []cli.Command {
    return []cli.Command{

        {
            Name:        "search",
            Flags:       getFlagSearch(),
            Subcommands: subCommandBookSearch(),
        },
    }
}

func subCommandBookSearch() []cli.Command {
    return []cli.Command{
        {
            Name:   "query",
            Action: actionQuery,
        },
        {
            Name:   "tag",
            Action: actionTag,
        },
    }
}

實現(xiàn) search query arg 命令


func actionQuery(c *cli.Context) {
    if c.NArg() == 1 {
        //fmt.Println(c.String("count"))
        url := fmt.Sprintf(bookSearchByQuery, c.Args().Get(0), strconv.Itoa(c.Int("count")))
        getBookSearch(url)
    }
}

具體實現(xiàn):

結(jié)構(gòu)體 和 模板輸出

type BookAll struct {
    BookCollection []BookInfo
}
type BookInfo struct {
    Title    string
    Subtitle string
    URL      string
    Isbn10   string
    Isbn13   string
    Price    string
}

func (b BookAll) Template() {
    t := template.New("New Template for book")
    t, _ = t.Parse(`
Show Book from DouBan Api:
    AllCollections:
        {{range .BookCollection}}
        Title: {{.Title}}
        Subtitle: {{.Subtitle}}
        URL: {{.URL}}
        Isbn10: {{.Isbn10}}
        Isbn13: {{.Isbn13}}
        Price: {{.Price}}
        {{end}}
`)
    t.Execute(os.Stdout, b)
}

具體http 請求處理:

func getBookSearch(url string) {
    var allBook []objects.BookInfo
    data := utils.Response(url, "books")
    for _, one := range data.Array() {
        var oneBook objects.BookInfo
        oneBook.Title = one.Get("title").String()
        oneBook.Subtitle = one.Get("subtitle").String()
        oneBook.Isbn10 = one.Get("isbn10").String()
        oneBook.Isbn13 = one.Get("isbn13").String()
        oneBook.URL = one.Get("url").String()
        oneBook.Price = one.Get("price").String()
        allBook = append(allBook, oneBook)
    }
    AllData := objects.BookAll{
        BookCollection: allBook,
    }
    AllData.Template()
}

func Response(url string, key string) gjson.Result {
    var newClient httpclient.HttpClient
    newClient = httpclient.Implement{}
    resp, err := newClient.Get(url)
    //fmt.Println(url)
    if err != nil {
        fmt.Println("Get HTTP Response Failed")
        return gjson.Result{}
    }
    if key == "" {
        return gjson.Parse(string(resp))
    } else {
        return gjson.Parse(string(resp)).Get(key)
    }
}

gjson 處理 是用來處理 json 的第三方庫桩引,非常好用。

上面我們使用框架收夸,一級一級實現(xiàn)下來坑匠,發(fā)現(xiàn)實際上我們只要聚焦實現(xiàn)業(yè)務:即http 請求 和 響應信息的處理即可。

5. 效果


YiYi.exe --help

YiYi is a tool for reading with DouBan and One APP api.                          
                                                                                 
                                                                                 
NAME:                                                                            
   YiYi - An application for book, movie, and story from DouBan and One App.     
                                                                                 
USAGE:                                                                           
   YiYi [global options] command [command options] [arguments...]                
                                                                                 
VERSION:                                                                         
                                                                                 
    ___       ___       ___       ___                                            
   /\__\     /\  \     /\__\     /\  \                                           
  |::L__L   _\:\  \   |::L__L   _\:\  \                                          
  |:::\__\ /\/::\__\  |:::\__\ /\/::\__\                                         
  /:;;/__/ \::/\/__/  /:;;/__/ \::/\/__/                                         
  \/__/     \:\__\    \/__/     \:\__\                                           
             \/__/               \/__/   v0.0.1                                  
                                                                                 
                                                                                 
DESCRIPTION:                                                                     
   An application for book, movie, and story from DouBan and One App.            
                                                                                 
AUTHOR:                                                                          
   xieWei <wuxiaoshen@shu.edu.cn>                                                
                                                                                 
COMMANDS:                                                                        
     book     get book info from DouBan API                                      
     story    get story info from One API                                        
     movie    get movie info from DouBan API                                      
     help, h  Shows a list of commands or help for one command                   
                                                                                 
GLOBAL OPTIONS:                                                                  
   --help, -h     show help                                                      
   --version, -v  print the version                                              


YiYi.exe book search query Golang


返回信息

Show Book from DouBan Api:
    AllCollections:

            Title: Cloud Native programming with Golang: Develop microservice-based high performance web apps for the cloud with Go
            Subtitle: Discover practical techniques to build cloud-native apps that are scalable, reliable, and always available.
            URL: https://api.douban.com/v2/book/30154908
            Isbn10: 178712598X
            Isbn13: 9781787125988
            Price: USD 44.99

            Title: Building RESTful Web services with Go: Learn how to build powerful RESTful APIs with Golang that scale gracefully
            Subtitle: Explore the necessary concepts of REST API development by building few real world services from scratch.
            URL: https://api.douban.com/v2/book/30154905
            Isbn10: 1788294289
            Isbn13: 9781788294287
            Price: USD 44.99

            Title: Go Standard Library Cookbook: Over 120 specific ways to make full use of the standard library components in Golang
            Subtitle: Implement solutions by leveraging the power of the GO standard library and reducing dependency on external crates
            URL: https://api.douban.com/v2/book/30179004
            Isbn10: 1788475275
            Isbn13: 9781788475273
            Price: USD 49.99

            Title: Go語言編程
            Subtitle:
            URL: https://api.douban.com/v2/book/11577300
            Isbn10: 7115290369
            Isbn13: 9787115290366
            Price: 49.00元

            Title: The Go Programming Language
            Subtitle:
            URL: https://api.douban.com/v2/book/26337545
            Isbn10: 0134190440
            Isbn13: 9780134190440
            Price: USD 39.99

            Title: Go Web編程
            Subtitle:
            URL: https://api.douban.com/v2/book/24316255
            Isbn10: 7121200910
            Isbn13: 9787121200915
            Price: 65.00元

            Title: Go語言學習筆記
            Subtitle:
            URL: https://api.douban.com/v2/book/26832468
            Isbn10: 7121291606
            Isbn13: 9787121291609
            Price: 89

            Title: Go 語言程序設計
            Subtitle:
            URL: https://api.douban.com/v2/book/24869910
            Isbn10: 7115317909
            Isbn13: 9787115317902
            Price: CNY 69.00

            Title: Go程序設計語言
            Subtitle:
            URL: https://api.douban.com/v2/book/27044219
            Isbn10: 7111558421
            Isbn13: 9787111558422
            Price: 79

            Title: Go并發(fā)編程實戰(zhàn)
            Subtitle: Go并發(fā)編程實戰(zhàn)
            URL: https://api.douban.com/v2/book/26244729
            Isbn10: 7115373981
            Isbn13: 9787115373984
            Price: 89元

            Title: Go in Action
            Subtitle:
            URL: https://api.douban.com/v2/book/25858023
            Isbn10: 1617291781
            Isbn13: 9781617291784
            Price: USD 39.99

具體用法:

YiYi 幫助文檔

項目地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末咱圆,一起剝皮案震驚了整個濱河市笛辟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌序苏,老刑警劉巖手幢,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異忱详,居然都是意外死亡围来,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門匈睁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來监透,“玉大人,你說我怎么就攤上這事航唆≌吐” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵糯钙,是天一觀的道長粪狼。 經(jīng)常有香客問我,道長任岸,這世上最難降的妖魔是什么再榄? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮享潜,結(jié)果婚禮上困鸥,老公的妹妹穿的比我還像新娘。我一直安慰自己剑按,他們只是感情好疾就,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著艺蝴,像睡著了一般虐译。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上吴趴,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天漆诽,我揣著相機與錄音侮攀,去河邊找鬼。 笑死厢拭,一個胖子當著我的面吹牛兰英,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播供鸠,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼畦贸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了楞捂?” 一聲冷哼從身側(cè)響起薄坏,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎寨闹,沒想到半個月后胶坠,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡繁堡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年沈善,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片椭蹄。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡闻牡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出绳矩,到底是詐尸還是另有隱情罩润,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布翼馆,位于F島的核電站哨啃,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏写妥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一审姓、第九天 我趴在偏房一處隱蔽的房頂上張望珍特。 院中可真熱鬧,春花似錦魔吐、人聲如沸扎筒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嗜桌。三九已至,卻和暖如春辞色,著一層夾襖步出監(jiān)牢的瞬間骨宠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留层亿,地道東北人桦卒。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像匿又,于是被迫代替她去往敵國和親方灾。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 官網(wǎng) 中文版本 好的網(wǎng)站 Content-type: text/htmlBASH Section: User ...
    不排版閱讀 4,370評論 0 5
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理碌更,服務發(fā)現(xiàn)裕偿,斷路器,智...
    卡卡羅2017閱讀 134,628評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,744評論 25 707
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,773評論 6 342
  • 我回憶痛单,回憶這個暑假發(fā)生的一切嘿棘;我拼命,拼命去記住發(fā)生的每一件溫馨小事桦他;因為這個暑假蔫巩,對于我們而言,意義非凡快压。 回...
    reginali閱讀 236評論 0 1