<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          構(gòu)建Go命令行程序工具鏈

          共 4447字,需瀏覽 9分鐘

           ·

          2022-06-27 23:08

          偷懶的故事

          今天的推薦需要從一個(gè)偷懶的故事說起···

          話說不久前,需要輸出一個(gè)按發(fā)布時(shí)間排序的酷Go推薦的歷史文章列表,類似于這樣:

          于是乎,想著從GoCN上一篇一篇copy文章的標(biāo)題吧,5篇下來,手眼已經(jīng)不協(xié)調(diào)了,此時(shí)此刻才想起自己貌似是個(gè)碼農(nóng),此情此景那必須coding一段,讓代碼來輸出這個(gè)列表。

          思路很簡單,看一下GoCN文章列表的API,再看下鑒權(quán)方式(看header是通過cookie),然后就可以coding了,通過API拉取文章數(shù)據(jù),提取需要的字段再組裝成MD輸出就完事了!

          當(dāng)準(zhǔn)備一個(gè)main.go搞定的時(shí)候,本著對coding的敬畏,簡單的思考了一下程序的可讀性、拓展性,決定還是構(gòu)建一個(gè)比較完整的命令行程序,如下:

          主角登場

          那么要實(shí)現(xiàn)上圖的命令行提示,程序參數(shù)解析等,不借助于第三方包當(dāng)然也能實(shí)現(xiàn)。但,前人種好的大樹為哈不乘涼呢,在業(yè)界對于命令行工具的開發(fā)已經(jīng)有比較成熟的實(shí)現(xiàn),下面清楚本文的主角:

          • cobra:應(yīng)用命令行框架
          • pflag:命令行參數(shù)解析
          • viper:配置文件解析
          下面結(jié)合實(shí)際項(xiàng)目來看如何使用這三位大哥來構(gòu)建Go命令行程序。

          先簡單看下項(xiàng)目結(jié)構(gòu):

          .
          ├── cmd
          │   ├── pull.go
          │   └── root.go
          ├── config.yaml
          ├── file
          │   └── cool-go.md
          ├── go.mod
          ├── go.sum
          ├── gocn-cli
          └── main.go

          然后引入上面所推薦的三個(gè)庫:

          go get -u github.com/spf13/cobra@latest

          go get -u github.com/spf13/viper

          go get -u github.com/spf13/pflag

          Coding

          package cmd

          import (
              "fmt"
              "github.com/spf13/cobra"
              "github.com/spf13/viper"
              "os"
          )

          var (
              cfgFile string
          )

          func init() {
              cobra.OnInitialize(initConfig)
              
              // 解析配置文件參數(shù)
              rootCmd.PersistentFlags().StringVar(&cfgFile, "config""""config file (default is ./config.yaml)")
          }

          // initConfig viper加載配置文件
          func initConfig() {
              if cfgFile != "" {
                  viper.SetConfigFile(cfgFile)
              } else {
                  viper.AddConfigPath(".")
                  viper.SetConfigName("config")
              }
              
              if err := viper.ReadInConfig(); err != nil {
                  fmt.Println("Can't read config file:", err)
                  os.Exit(1)
              }
          }

          // 創(chuàng)建全局rootCmd
          var rootCmd = &cobra.Command{
              Use:   "gocn-cli",
              Short: "gocn-cli is a command line tool for gocn.com",
              Long:  "gocn-cli is a command line tool for gocn.com",
              Run: func(cmd *cobra.Command, args []string) {
                  
              },
          }

          // Execute 執(zhí)行命令 main調(diào)用
          func Execute() {
              if err := rootCmd.Execute(); err != nil {
                  fmt.Println(err)
                  os.Exit(1)
              }
          }

          package cmd

          import (
           "github.com/spf13/cobra"
           "github.com/spf13/viper"
           "os"
          )

          var (
           moduleName string
          )

          func init() {
              // 給rootCmd增加新的命令pullCmd
           rootCmd.AddCommand(pullCmd)

           pullCmd.Flags().StringVarP(&moduleName, "module""m""""module name")
          }

          var pullCmd = &cobra.Command{
           Use:   "pull gocn data",
           Short: "pull gocn data",
           Run: func(cmd *cobra.Command, args []string) {
            pullHandler()
           },
          }

          // pullHandler pullCmd 對應(yīng)的處理函數(shù)
          func pullHandler() {
           if moduleName == "" {
            fmt.Println("module name is required")
            os.Exit(1)
           }

           switch moduleName {
           case "cool-go":
            pullCoolGo()

           default:
            fmt.Println("module name is invalid")
            os.Exit(1)
           }
          }

          func pullCoolGo() {
           // TODO Write Your Code
          }

          結(jié)語

          以上簡單介紹了如何使用cobra、viper、pflag,當(dāng)然它們的用法還有很多,這里只做個(gè)簡單的入門。
          可見,通過簡單的代就能構(gòu)建出比較好的命令行程序。

          參考

          • https://github.com/spf13/cobra
          • https://github.com/spf13/viper
          • https://github.com/spf13/pflag


          往期推薦



          等等,怎么使用 SetMemoryLimit?


          第八屆 GopherChina 大會蓄勢待發(fā)!


          這不會又是一個(gè)Go的BUG吧?

          想要了解Go更多內(nèi)容,歡迎掃描下方?? 關(guān)注 公眾號,回復(fù)關(guān)鍵詞 [實(shí)戰(zhàn)群]  ,就有機(jī)會進(jìn)群和我們進(jìn)行交流

          分享、在看與點(diǎn)贊,至少我要擁有一個(gè)叭~

          瀏覽 62
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  影音先锋日韩三级片 | 4438全国最大成人网 | 丁香婷婷五月综合小说99在线 | 玖玖在线免费观看视频 | 亲子乱一区二区三区 |