精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

一個庫,用Go搞定命令行程序

開發 前端
Go 官方有一個 flags 庫提供了最基礎的命令行參數支持,不過確實不好用,今天帶你認識一個超贊的庫——urfave/cli,它能讓你用一種簡單優雅的方式來構建命令行程序。

我們平時做的Go項目除了寫的各種API接口外,還經常會寫任務腳本、命令行程序、定時任務等,其實這幾個是一個東西,你寫的任務腳本支持接受指令傳參,那它不就是命令行程序了?再把程序部署到服務器用Go Cron加個任務就是定時任務了。

圖片圖片

Go 官方有一個 flags 庫提供了最基礎的命令行參數支持,不過確實不好用,今天帶你認識一個超贊的庫——urfave/cli,它能讓你用一種簡單優雅的方式來構建命令行程序。

什么是urfave/cli?

urfave/cli 是一個用 Go 編寫的、簡單、快速且有趣的庫,用于構建命令行應用程序。無論是小工具還是復雜的大型 CLI 程序,它都能輕松應對。它的設計哲學是讓我們用聲明式的方式來定義命令、子命令、標志(Flags),然后它會自動幫你處理參數解析、幫助文檔生成等所有繁瑣的工作,聽起來是不是很棒?

安裝

運行以下命令來安裝 urfave/cli 的 v2 版本:

go get github.com/urfave/cli/v2

第一個 CLI 程序

我們從經典的 "Hello, World!" 開始,創建一個 main.go 文件,然后敲入以下代碼:

package main

import (
    "log"
    "os"

    "github.com/urfave/cli/v2"
)

func main() {
    app := &cli.App{
        Name:  "greet",
        Usage: "向世界打個招呼!",
        Action: func(c *cli.Context) error {
            println("Hello, world!")
            returnnil
        },
    }

    if err := app.Run(os.Args); err != nil {
        log.Fatal(err)
    }
}

運行命令程序

go run main.go

你會看到終端輸出了 Hello, world!,當然我們也可以 build 后用真正的命令去運行

# build
go build -o greet ./main.go 
# 運行命令
./greet

urfave/cli 自動為我們生成了幫助信息。上面這個命令運行時添加 --help 就能在控制臺輸出幫助信息。

添加命令行傳參

只會說 "Hello, world!" 可不夠,我們希望它能跟指定的人打招呼。這就要用到“標志”(Flags)了。

我們來修改一下代碼,添加一個 --name的標志:

package main

import (
    "fmt"
    "log"
    "os"

    "github.com/urfave/cli/v2"
)

func main() {
    app := &cli.App{
        Name:  "greet",
        Usage: "向世界或某人打個招呼!",
        Flags: []cli.Flag{
            &cli.StringFlag{
                Name:    "name",
                Value:   "world", // 默認值
                Usage:   "指定打招呼的對象",
                Aliases: []string{"n"}, // 別名,-n 等同于 --name
            },
        },
        Action: func(c *cli.Context) error {
            name := c.String("name")
            fmt.Printf("Hello, %s!\n", name)
            returnnil
        },
    }

    if err := app.Run(os.Args); err != nil {
        log.Fatal(err)
    }
}

現在重新打包構建一下這個命令

$ go build -o greet ./main.go
# 不帶任何參數,使用默認值
$ ./greet
Hello, world!

# 使用 --name 標志
$ ./greet --name Gopher
Hello, Gopher!

# 使用別名 -n
$ ./greet -n 狗蛋
Hello, 狗蛋!

命令和子命令

當你的工具功能越來越復雜時,就需要引入“命令” 和 “子命令”來組織功能了。這就像 git 有 commit、push、pull 等子命令一樣。我們來模擬一個簡單的文件處理工具 filetool。

package main

import (
    "fmt"
    "log"
    "os"

    "github.com/urfave/cli/v2"
)

func main() {
    app := &cli.App{
        Name:  "filetool",
        Usage: "一個簡單的文件處理工具",
        Commands: []*cli.Command{
            {
                Name:    "hash",
                Aliases: []string{"h"},
                Usage:   "計算文件的哈希值",
                Flags: []cli.Flag{
                    &cli.StringFlag{
                        Name:     "file",
                        Aliases:  []string{"f"},
                        Usage:    "指定輸入文件",
                        Required: true, // 這是一個必填項!
                    },
                },
                Action: func(c *cli.Context) error {
                    filePath := c.String("file")
                    // 這里的 hashFile 是我們自己實現的邏輯函數
                    fmt.Printf("正在為文件 '%s' 計算哈希...\n", filePath)
                    returnnil
                },
            },
        },
    }

    if err := app.Run(os.Args); err != nil {
        log.Fatal(err)
    }
}

上面是添加了命令,對于復雜的命令行程序,尤其是在業務系統里用作處理數據的命令行程序,往往還需要子命令的支持。這樣我們可以把處理一個大類數據的任務都劃分到同一個命令下,每個細分任務在寫成命令的子命令。

下面是一個添加子命令的簡單例子:

var Word = &cli.Command{
 Name:    "word",
 Aliases: []string{"w"},
 Usage:   "Word文檔處理相關命令",
 Subcommands: []*cli.Command{
  {
   Name:  "parse",
   Usage: "解析Word文檔",
   Flags: []cli.Flag{
    &cli.StringFlag{
     Name:     "input",
     Aliases:  []string{"i"},
     Usage:    "輸入文件路徑",
     Required: true,
    },
    &cli.StringFlag{
     Name:     "output",
     Aliases:  []string{"o"},
     Usage:    "輸出文件路徑",
     Required: true,
    },
   },
   Action: func(c *cli.Context) error {
    return logic.NewWordLogic(c.Context).ParseWord(c.String("input"), c.String("output"))
   },
  },
 },
}

我們把這個子命令加到上面的

func main() {
    app := &cli.App{
        Name:  "filetool",
        Usage: "一個簡單的文件處理工具",
        Commands: []*cli.Command{
            // ......
            word,
            // 添加更多命令
        },
    }
    // ......
}

上面這個子命令的調用方式如下:

$ go build -o filetool ./main.go;
./filetool word parse -i input.docx -o output.txt

最佳實踐

基礎用法已經掌握了,但要構建一個健壯、可維護的命令行工具,我們還需要借鑒一些真實項目中的經驗。下面這些技巧,能讓你的代碼質量提升一個臺階。

鉤子函數:用 Before和 After統一處理邏輯

你可能希望在每個命令執行前后都做一些固定的操作,比如初始化日志、設置鏈路追蹤、上報監控數據或者記錄執行時間等。urfave/cli 提供了 Before 和 After 鉤子函數,來解決這個問題。

下面是我的專欄項目使用 urfave/cli 時添加的鉤子:

func main() {
 app := &cli.App{
  Name:  "gm-tools",
  Usage: "Go Mall 工具集",
  Before: func(c *cli.Context) error {
   // 為每個命令創建帶有追蹤信息的上下文
   ctx := context.Background()
   spanId := util.GenerateSpanID(util.GetLocalIP())
   ctx = context.WithValue(ctx, "spanid", spanId)
   c.Context = ctx

   cmdName := strings.Join(c.Args().Slice(), " ")
   logger.Info(ctx, fmt.Sprintf("定時任務【%s】開始執行. 時間=【%s】)", cmdName, time.Now().Format(enum.TimeFormatHyphenedYMDHIS)))
   returnnil
  },
  After: func(c *cli.Context) error {
   // 記錄執行的錯誤
   if c.Context.Err() != nil {
    logger.Error(c.Context, "定時任務執行失敗", c.Context.Err())
   }
   cmdName := strings.Join(c.Args().Slice(), " ")
   logger.Info(c.Context, fmt.Sprintf("定時任務【%s】執行完成. 時間=【%s", cmdName, time.Now().Format(enum.TimeFormatHyphenedYMDHIS)))
   returnnil
  },
  Commands: []*cli.Command{
   commands.Word,
   // 添加更多工具命令
  },
 }

if err := app.Run(os.Args); err != nil {
  log.Fatal(err)
 }
}

這樣無論你運行哪個命令,Before 和 After 里的日志都會被打印出來。更重要的是,我們將一個帶有追蹤信息的 Go context.Context 注入到了 cli.Context 中,在后續的 Action 函數里,我們可以通過 c.Context 取出這個上下文,并把它傳遞給業務邏輯,實現了全鏈路的追蹤!

責任編輯:武曉燕 來源: 網管叨bi叨
相關推薦

2023-03-31 08:44:55

Go開發命令

2016-03-28 10:00:09

Swift命令程序

2022-06-07 07:21:19

Python內置庫命令行

2010-07-15 10:58:23

Perl命令行程序

2019-04-16 06:50:34

2020-02-13 10:57:59

Python數據設計

2020-12-08 08:46:07

GoJava工具

2015-07-15 10:32:44

Node.js命令行程序

2022-09-23 09:50:45

Python

2022-09-27 13:07:41

clickPython命令行

2011-06-17 16:49:05

Cocoa蘋果

2018-06-12 15:10:11

Linuxvim命令PacVim

2019-06-10 15:00:27

node命令行前端

2023-10-30 01:00:42

Go語言Cobra庫

2018-11-21 09:57:44

命令行Linux文件

2016-08-10 12:41:00

Linux工具bcShell

2017-05-27 14:45:04

Linux命令進程

2022-02-17 18:21:47

工具HTTPie客戶端

2018-05-03 12:35:05

Linux命令Pet

2019-08-20 10:02:35

點贊
收藏

51CTO技術棧公眾號

欧美日韩视频在线一区二区| 国产精品一区二区久激情瑜伽 | 欧美激情女人20p| 国内精品免费视频| gay欧美网站| 亚洲欧美日韩国产综合在线| 国产伦精品一区二区三毛| 一级片免费在线播放| 自拍日韩欧美| 国产亚洲欧洲高清| 被黑人猛躁10次高潮视频| 波多野结衣亚洲一二三| 亚洲日本va在线观看| 欧美日韩一区二区三| 国产sm主人调教女m视频| 香蕉久久国产| 久久久亚洲成人| 国产成人免费在线观看视频| 久久av国产紧身裤| 欧美一级欧美一级在线播放| 精品久久久久久久无码| h片精品在线观看| 中文字幕在线不卡视频| 欧美亚洲一级二级| 你懂的网站在线| 国产麻豆视频精品| 国产精自产拍久久久久久| 亚洲欧美偷拍视频| 99伊人成综合| 欧美激情一区二区三区在线视频观看| 亚洲天堂av中文字幕| 亚洲精品一级二级三级| 亚洲韩国日本中文字幕| 极品白嫩少妇无套内谢| 成人av在线播放| 欧美日韩成人高清| 免费涩涩18网站入口| 欧洲av不卡| 天天综合天天综合色| 无码人妻精品一区二区三区99v| 爱久久·www| 国产无一区二区| 六月婷婷久久| 熟妇人妻中文av无码| 成人综合婷婷国产精品久久蜜臀| 91亚洲精品久久久久久久久久久久| 老熟妇一区二区三区啪啪| 久久精选视频| 日本最新高清不卡中文字幕| 青草视频在线观看免费| 欧美大片专区| 色综合视频一区中文字幕| 日本在线一级片| 欧美成人一品| 国内精品一区二区三区四区| 国产无码精品久久久| 亚洲韩日在线| 久久久亚洲网站| 国产精品500部| 一区二区激情| 国产成人一区二区三区小说| 免费黄色片视频| 另类人妖一区二区av| 91精品国产自产在线| 国产强伦人妻毛片| 国产99一区视频免费| 国产精品伊人日日| 手机看片福利在线观看| 久久免费精品国产久精品久久久久| 欧美成人综合一区| 97超碰人人在线| 亚洲欧美一区二区久久| 黄色特一级视频| 久久男人av资源站| 欧洲另类一二三四区| 天堂av8在线| 白白在线精品| 亚洲欧美中文在线视频| 欧美a级片免费看| 狠狠88综合久久久久综合网| 欧美一区二区.| 91久久精品无码一区二区| 国产乱一区二区| 好吊色欧美一区二区三区视频 | 久久久91麻豆精品国产一区| 精品久久久久久久久久久久包黑料 | 99久久99久久精品免费看蜜桃| 欧美日产一区二区三区在线观看| 日本在线免费看| 亚洲大尺度视频在线观看| 天天摸天天碰天天添| 999精品视频在线观看| 精品福利一二区| 一区二区三区在线观看免费视频| 欧美.www| 国产精品wwwwww| 亚洲国产日韩在线观看| 国产网站一区二区三区| 91网站在线观看免费| 无人区在线高清完整免费版 一区二| 欧美精品久久一区二区三区| 亚洲黄色免费在线观看| 91蜜臀精品国产自偷在线| 久久久午夜视频| 91一区二区视频| 久久这里只精品最新地址| 一本色道久久99精品综合| 免费看男女www网站入口在线| 欧美日本一区二区三区| free性中国hd国语露脸| 一区二区三区四区在线观看国产日韩| 国产91热爆ts人妖在线| 粉嫩av一区二区夜夜嗨| 国产精品久久久久久久浪潮网站 | 欧美日韩国产观看视频| 91精品国产综合久久蜜臀| 亚洲精品视频久久久| 欧美91视频| 国产日韩欧美在线播放| 可以直接在线观看的av| 性做久久久久久免费观看| 午夜免费视频网站| 成人a'v在线播放| 日韩av成人在线| 婷婷视频在线观看| 亚洲一二三专区| 麻豆精品国产传媒| 亚洲国产老妈| 成人中心免费视频| 午夜不卡视频| 欧美色偷偷大香| 性欧美精品男男| 久久福利一区| 欧美另类高清视频在线| 黄色污网站在线观看| 精品国产自在久精品国产| 国产97免费视频| 精品无人码麻豆乱码1区2区| 亚洲国产婷婷香蕉久久久久久99| 欧美三级网址| 亚洲区一区二区| 中文字幕黄色片| 久久人人97超碰com| 日本毛片在线免费观看| 日韩精品免费一区二区三区竹菊 | 中文字幕av久久爽| 日本一区二区视频在线观看| 久久综合伊人77777麻豆最新章节| 免费精品国产| 国产精品黄色影片导航在线观看| 国产资源在线看| 欧美三级在线看| 免费看的黄色录像| 国产麻豆精品在线| 欧美乱做爰xxxⅹ久久久| 成人精品毛片| 欧美性受xxx| 九色视频在线观看免费播放| 欧美亚洲一区二区三区四区| 手机看片国产日韩| 国内精品久久久久影院色| 熟妇熟女乱妇乱女网站| ccyy激情综合| 欧美一区在线直播| 啊v视频在线| 欧美色精品天天在线观看视频| 999福利视频| 国产成人欧美日韩在线电影| 欧美日韩不卡在线视频| 免费视频国产一区| 国产欧美婷婷中文| 青青草原国产在线| 亚洲免费电影一区| 一本色道久久综合亚洲| 一区二区三区在线影院| 中文字幕三级电影| 久久看片网站| 亚洲一区二区在线看| 亚洲精品高潮| 欧美做爰性生交视频| 免费黄网在线观看| 亚洲第一中文字幕| 波多野结衣mp4| 亚洲免费色视频| 欧洲一级黄色片| 麻豆专区一区二区三区四区五区| 97久久国产亚洲精品超碰热| 中日韩免视频上线全都免费| 成人h猎奇视频网站| av手机免费在线观看| 中文字幕不卡在线视频极品| 肥臀熟女一区二区三区| 欧美在线播放高清精品| 国产黄色片视频| 国产欧美日韩在线视频| 娇妻高潮浓精白浆xxⅹ| 免费人成在线不卡| 久久亚洲中文字幕无码| 999久久久精品国产| 九色视频成人porny| 伊人久久综合网另类网站| 7m第一福利500精品视频| 蜜桃视频在线观看www社区| 精品呦交小u女在线| aaa一区二区三区| 日本精品视频一区二区三区| 国产一级aa大片毛片| 国产亚洲欧美激情| 亚洲精品成人无码毛片| 毛片av一区二区三区| 黑人糟蹋人妻hd中文字幕| 你懂的成人av| 亚洲综合av一区| 免费不卡中文字幕在线| 国产一区二区无遮挡| 99热这里有精品| 国产成一区二区| 丁香高清在线观看完整电影视频| 久久精品久久久久久| 玖玖综合伊人| 日韩精品黄色网| 亚洲免费不卡视频| 666欧美在线视频| 五月激情丁香网| 色婷婷久久一区二区三区麻豆| 久久免费视频99| 亚洲精品乱码久久久久久黑人| 高清国产在线观看| 久久久久国产精品麻豆ai换脸| 欧美精品欧美极品欧美激情| 成人美女视频在线观看| 成人啪啪18免费游戏链接| 国产精品一区二区在线观看网站| www.se五月| 久久精品国产免费看久久精品| 国产天堂在线播放| 久久一区视频| 国产成人手机视频| 久久性色av| 国产三级日本三级在线播放| 久久一区精品| 天天操天天爽天天射| 日本亚洲一区二区| 天天色综合社区| 麻豆精品在线视频| 中文字幕久久av| 国产伦理精品不卡| 中文字幕在线观看91| 国产成人精品影视| 国产精品久久久久久亚洲av| 丁香天五香天堂综合| 手机免费看av片| 97aⅴ精品视频一二三区| 日本japanese极品少妇| 91论坛在线播放| 一级黄色录像毛片| 国产精品久久久久久久久免费樱桃| 天天看天天摸天天操| 亚洲精品免费在线| 国产精品变态另类虐交| 婷婷开心激情综合| 欧美日韩a v| 欧美人牲a欧美精品| 国产情侣在线播放| 欧美大片顶级少妇| 天天摸天天干天天操| 亚洲色图15p| 午夜伦理在线| 欧美激情欧美狂野欧美精品| 亚洲福利影院| 国产欧美日韩91| 亚洲日本va午夜在线电影| 精品在线视频一区二区三区| 黑人操亚洲人| 国产性生活免费视频| 国产欧美一级| 久久久久久久久久一区| 成人自拍视频在线| 波多野吉衣中文字幕| 国产精品国产三级国产三级人妇| 久久久久成人网站| 色婷婷久久久久swag精品| 国产免费视频一区二区三区| 日韩电影第一页| 黄色网在线看| 欧美一区二区三区图| 欧美高清你懂的| 久久久久久九九九九| 99精品小视频| www黄色av| 国产乱码精品一品二品| 在哪里可以看毛片| 一区二区三区免费在线观看| 中文人妻av久久人妻18| 欧美电影免费提供在线观看| 精品视频三区| 久久人91精品久久久久久不卡| 在线观看精品| 国产日韩欧美一区二区三区四区| 日韩国产一区二区三区| 人妻久久久一区二区三区| 国产最新精品精品你懂的| 亚洲天堂久久新| 亚洲影视在线观看| 一级黄色免费片| 亚洲欧美激情一区| av在线网页| 91在线视频一区| 欧美日中文字幕| 日韩av在线第一页| 国产麻豆精品theporn| 国产午夜福利一区| 欧美日韩亚洲网| 亚洲a视频在线观看| 日韩在线观看av| 91精品国产经典在线观看| 久久riav二区三区| 黄色另类av| 精品人妻一区二区三区免费| 国产精品美女视频| 欧美成人精品网站| 亚洲男人天堂九九视频| 成年女人在线看片| wwwxx欧美| 欧美精品二区| 色姑娘综合天天| 国产精品九色蝌蚪自拍| www.久久网| 亚洲人成人99网站| 欧美1级2级| 欧洲成人一区二区| 可以看av的网站久久看| 精品久久久久久中文字幕人妻最新| 亚洲成av人综合在线观看| 国产白浆在线观看| 久久中文字幕国产| 精品亚洲二区| 欧美交换配乱吟粗大25p| 国产乱理伦片在线观看夜一区 | 一区二区在线| 国产精品久久久久久9999| 亚洲青青青在线视频| 999国产精品视频免费| 久久夜色精品国产| 国产在线一区不卡| 成人国产在线看| 成人爽a毛片一区二区免费| 精品在线视频免费| 亚洲精品国产美女| 欧美自拍电影| 亚洲五月六月| 国产伦精品一区二区三区免费| 久久久美女视频| 精品亚洲va在线va天堂资源站| 中日韩脚交footjobhd| 日本欧洲国产一区二区| 免费精品视频在线| 国产一区二区播放| 亚洲第一男人天堂| 成人av三级| 亚洲日本理论电影| 国产一区二区看久久| 精品无码m3u8在线观看| 日韩av在线电影网| 中文字幕日本一区二区| 欧美亚洲视频一区| 成人精品免费视频| www.色国产| 久久精品男人天堂| 乱中年女人伦av一区二区| 成人中文字幕av| 亚洲少妇屁股交4| 香蕉av在线播放| 国产精品美女主播在线观看纯欲| 国产精品久久久久久久久久10秀| 国产xxxxhd| 欧美午夜电影在线| 日韩伦理在线电影| 国产精品伊人日日| 日本伊人精品一区二区三区观看方式| 澳门黄色一级片| 亚洲精品永久免费精品| 国产精品1区| 日批视频在线免费看| 中文字幕中文乱码欧美一区二区| 噜噜噜久久,亚洲精品国产品| 国产成人精品午夜| 国语精品一区| 成熟人妻av无码专区| 日韩美女视频在线| 成人啊v在线| 老太脱裤子让老头玩xxxxx| 国产精品久久免费看| 无码精品黑人一区二区三区| 国产欧美va欧美va香蕉在线| 免费视频一区二区三区在线观看| 澳门黄色一级片| 中文字幕日韩高清| 爽爽窝窝午夜精品一区二区| 亚洲五月激情网|