色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
电子发烧友
开通电子发烧友VIP会员 尊享10大特权
海量资料免费下载
精品直播免费看
优质内容免费畅学
课程9折专享价
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Golang基于flag庫實(shí)現(xiàn)一個(gè)命令行工具

馬哥Linux運(yùn)維 ? 來源:稀土掘金技術(shù)社區(qū) ? 作者: ag9920 ? 2022-10-28 09:26 ? 次閱讀

Golang 標(biāo)準(zhǔn)庫中的 flag 庫提供了解析命令行選項(xiàng)的能力,我們可以基于此來開發(fā)命令行工具。

假設(shè)我們想做一個(gè)命令行工具,我們通過參數(shù)提供【城市】,它自動(dòng)能夠返回當(dāng)前這個(gè)【城市】的天氣狀況。這樣一個(gè)簡單的需求,今天我們就來試一下,看怎樣實(shí)現(xiàn)。


flag 庫

Package flag implements command-line flag parsing.

flag 庫[1]能夠支持基礎(chǔ)的命令行 flag 解析。使用起來并不復(fù)雜,

我們可以針對(duì) string, integer, bool 三種類型來定義 flag,如:flag.String(), Bool(), Int()。

b0028a96-5614-11ed-a3b6-dac502259ad0.png
b01bc894-5614-11ed-a3b6-dac502259ad0.png

比如下面這樣,我們就定義了一個(gè)-n的選項(xiàng),默認(rèn)值為 1234, 提示信息為help message for flag n。返回值是一個(gè) int 的指針。

import "flag"
var nFlag = flag.Int("n", 1234, "help message for flag n")

當(dāng)然,我們也可以直接將 flag 和變量綁定,這里要在上面三種方法的前面加上 Var 即可:

var flagvar int
func init() {
 flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
}

區(qū)別只在于首個(gè)參數(shù)是個(gè)指針,直接賦值,而不是 return 回來。簽名都是類似的,我們看一個(gè) Int64Var:

b02fdcf8-5614-11ed-a3b6-dac502259ad0.jpg

在所有 flag 都定義好之后,我們調(diào)用flag.Parse()方法,將命令行數(shù)據(jù)解析到對(duì)應(yīng)的 flag 中。這之后就可以直接用了:

fmt.Println("ip has value ", *ip)
fmt.Println("flagvar has value ", flagvar)

有時(shí)候我們不止是一個(gè)簡單的 flag,還需要參數(shù),這個(gè)時(shí)候我們就可以用flag.Args()拿到一個(gè) slice,或者直接flag.Arg(i)來拿指定參數(shù),下標(biāo)從 0 開始。

b0494620-5614-11ed-a3b6-dac502259ad0.png

不熟悉的同學(xué)建議多看看看go by example[2]的示例,講的很清楚。

開發(fā)者的角度看,其實(shí)我們只要定義好變量,用 flag.XXVar 來綁定,最后 flag.Parse 就可以用:

package main


import (
  "fmt"
  "flag"
)


var (
  intflag int
  boolflag bool
  stringflag string
)


func init() {
  flag.IntVar(&intflag, "intflag", 0, "int flag value")
  flag.BoolVar(&boolflag, "boolflag", false, "bool flag value")
  flag.StringVar(&stringflag, "stringflag", "default", "string flag value")
}


func main() {
  flag.Parse()


  fmt.Println("int flag:", intflag)
  fmt.Println("bool flag:", boolflag)
  fmt.Println("string flag:", stringflag)
}

編譯之后我們運(yùn)行一下看看

$ ./main -intflag 12 -boolflag 1 -stringflag test


int flag: 12
bool flag: true
string flag: test

如果沒有設(shè)置 flag 的值,會(huì)取我們?cè)O(shè)置的默認(rèn)值。

flag 支持的解析類型有下面四種

-flag

--flag

-flag=x

-flag x (bool 不能用這個(gè))

有時(shí)候我們只需要一個(gè) flag 就夠了,選項(xiàng)本身就帶著含義,不需要參數(shù)。而有些時(shí)候我們既需要 flag,也需要參數(shù)。注意區(qū)分好場(chǎng)景即可。如果用了第一種和第二種這種不帶參數(shù)的,本質(zhì)含義就是個(gè) bool,出現(xiàn)就是 true,不出現(xiàn)就看默認(rèn)值。

FlagSet

FlagSet 就是一組 flag 定義的集合,在 flag 庫的底層是一個(gè)結(jié)構(gòu)體:

type FlagSet struct {
 // Usage is the function called when an error occurs while parsing flags.
 // The field is a function (not a method) that may be changed to point to
 // a custom error handler. What happens after Usage is called depends
 // on the ErrorHandling setting; for the command line, this defaults
 // to ExitOnError, which exits the program after calling Usage.
 Usage func()
 // contains filtered or unexported fields
}

注意有一個(gè) Usage 函數(shù),當(dāng)解析 flag 出問題時(shí)就會(huì)調(diào)用這個(gè)。前面 flag 庫封裝的那些能力底層都是共用同一個(gè)默認(rèn)的 CommandLine FlagSet實(shí)現(xiàn)的:

// src/flag/flag.go
var CommandLine = NewFlagSet(os.Args[0], ExitOnError)


func Parse() {
  CommandLine.Parse(os.Args[1:])
}


func IntVar(p *int, name string, value int, usage string) {
  CommandLine.Var(newIntValue(value, p), name, usage)
}


func Int(name string, value int, usage string) *int {
  return CommandLine.Int(name, value, usage)
}


func NFlag() int { return len(CommandLine.actual) }


func Arg(i int) string {
  return CommandLine.Arg(i)
}


func NArg() int { return len(CommandLine.args) }

當(dāng)我們調(diào)用 NewFlagSet 時(shí)需要指定這個(gè)集合的名稱以及對(duì)應(yīng)的錯(cuò)誤處理。

b05cece8-5614-11ed-a3b6-dac502259ad0.jpg

第二個(gè)參數(shù)這個(gè)錯(cuò)誤處理有三種選項(xiàng),flag 已經(jīng)提供

ContinueOnError:發(fā)生錯(cuò)誤后繼續(xù)解析,CommandLine就是使用這個(gè)選項(xiàng);

ExitOnError:出錯(cuò)時(shí)調(diào)用os.Exit(2)退出程序;

PanicOnError:出錯(cuò)時(shí)產(chǎn)生 panic。

需求拆解

我們的需求很簡單,提供一個(gè) weather flag,接受輸入的城市名稱,隨后我們返回天氣數(shù)據(jù)即可。

所以,從 flag 的角度看,這里并不復(fù)雜,我們將【城市名稱】綁定到一個(gè) flag 上即可。

關(guān)鍵是要實(shí)現(xiàn)基于城市名稱查天氣的能力。這個(gè)也有公開的網(wǎng)站能實(shí)現(xiàn),參照此前 Golang 教程中給出的 wttr 就可以。大家可以試一下,訪問wttr.in/wuhan[3]將會(huì)展示【武漢】的天氣預(yù)報(bào):

b0709f0e-5614-11ed-a3b6-dac502259ad0.jpg

這里其實(shí)比較 trick,由于是網(wǎng)站,并不是公開的 open api,所以返回的數(shù)據(jù)也是 html 格式的,我們要思考一下怎么在命令行展示。

下面我們一步步來解決。

實(shí)現(xiàn) weather flag

這一步基本是復(fù)用 flag 包提供的能力,這里我們用 StringVar 從命令行拿到值之后寫入變量,這里相對(duì)比較通用,大家以后有需求可以直接改一下即可:

package main


import (
    "flag"
    "fmt"
    "os"
)


type arguments struct {
 weatherCity string
}


func (a *arguments) parseArgs(args []string) error {
 f := flag.NewFlagSet(os.Args[0], flag.ContinueOnError)


 f.StringVar(&a.weatherCity, "weather", "", "check weather")


 f.Usage = func() {
  fmt.Fprintf(os.Stderr, `flags: %s`, os.Args[0])
  f.PrintDefaults()
  os.Exit(1)
 }
 if err := f.Parse(args[1:]); err != nil {
  return err
 }


 return nil
}


func Execute() error {


 args := &arguments{}
 if err := args.parseArgs(os.Args); err != nil {
  fmt.Println(err)
  os.Exit(2)
 }


 // weather
 if args.weatherCity != "" {
                // TODO 實(shí)現(xiàn)根據(jù) city 名稱拿天氣,并打印的效果
 }


 return nil
}

最終在 main() 函數(shù)中直接調(diào)用我們的 Execute 即可,注意我們解析到 weatherCity 不為空時(shí),核心邏輯就在這個(gè)分支,我們留了個(gè) TODO,下面看看怎么解。

天氣數(shù)據(jù)打印

前一節(jié)的 TODO 里本質(zhì)需要我們實(shí)現(xiàn)的簽名很簡單:

func GetWeather(city string) (string, error)

這樣拿到一個(gè)用字符串表示的天氣數(shù)據(jù),然后回到主流程里一個(gè)fmt.Printf就可以解決。

而同時(shí)我們也有了 wttr 的能力,可以拿到數(shù)據(jù),只不過是 html。關(guān)鍵是怎么轉(zhuǎn)字符串。我們一步一步來:

獲取源數(shù)據(jù)

一個(gè)簡單的 http.Get 拿到 html 數(shù)據(jù)即可,這一步不復(fù)雜,大家直接看代碼:

func getWeatherData(city string) string {
    url := "https://wttr.in/" + city
    response, err := http.Get(url)
    if err != nil {
            return "", err
    }
    all, err := ioutil.ReadAll(response.Body)
    if err != nil {
            return "", err
    }
    weather := string(all)
    return weather
}

數(shù)據(jù)轉(zhuǎn)換

在開源社區(qū),我們找到了"github.com/JohannesKaufmann/html-to-markdown"這個(gè)庫提供 html 轉(zhuǎn)換為 markdown 的能力,而"github.com/MichaelMure/go-term-markdown"又可以將 markdown 格式轉(zhuǎn)為可在 terminal 打印的字符串,我們可以通過這兩步來轉(zhuǎn)換,實(shí)現(xiàn)整體的 GetWeather 函數(shù):

package weather


import (
 "io/ioutil"
 "net/http"


 md "github.com/JohannesKaufmann/html-to-markdown"
 markdown "github.com/MichaelMure/go-term-markdown"
)


func GetWeather(city string) (string, error) {
 url := "https://wttr.in/" + city
 response, err := http.Get(url)
 if err != nil {
  return "", err
 }
 all, err := ioutil.ReadAll(response.Body)
 if err != nil {
  return "", err
 }
 weather := string(all)
 md := getMD(weather)
 result := markdown.Render(md, 280, 6)
 return string(result), nil
}


func getMD(html string) string {
 converter := md.NewConverter("", true, nil)
 markdown, err := converter.ConvertString(html)
 if err != nil {
  return ""
 }
 return markdown
}

運(yùn)行效果

好了,現(xiàn)在我們實(shí)現(xiàn)了兩步,大家只需要把主流程里 TODO 的注釋換成實(shí)際對(duì)下面 GetWeather 函數(shù)的調(diào)用即可,我們來看看運(yùn)行效果。

$ opb -weather beijing

b084f92c-5614-11ed-a3b6-dac502259ad0.jpg

完美,一個(gè)展示天氣狀況的命令行工具就做完了。這里的 opb 是我們的 package 名稱,大家可以自己試一下,包名更換為你喜歡的名稱即可。

小結(jié)

其實(shí)開源社區(qū)各種能力基本都有同學(xué)研究過,大家可以打開思路,碰到知識(shí)點(diǎn)就思考如何能落地。筆者也是初學(xué) flag 的時(shí)候本著實(shí)踐的目的來試一試。正好發(fā)現(xiàn)了 html => markdown => terminal 打印這條路徑,不一定是最好的,但作為一個(gè) toy tool 足夠了。

今天我們只是展示了下 flag 包的基礎(chǔ)能力,建議示例代碼大家都嘗試跑一下看看,感興趣的同學(xué)可以進(jìn)一步了解如何基于 flag 包封裝出更高級(jí)的應(yīng)用。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Flag
    +關(guān)注

    關(guān)注

    0

    文章

    12

    瀏覽量

    8286
  • 命令行
    +關(guān)注

    關(guān)注

    0

    文章

    80

    瀏覽量

    10542

原文標(biāo)題:Golang 基于 flag 庫實(shí)現(xiàn)一個(gè)命令行工具

文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 0人收藏

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    在STM32實(shí)現(xiàn)命令行

    工作中的開發(fā)環(huán)境都是基于linux命令行交互,作為命令行的重度使用者,玩單片機(jī)也要使用命令行工具,百度了
    發(fā)表于 12-09 11:32 ?3012次閱讀

    Linux命令行工具

    Linux 新手往往對(duì)命令行心存畏懼。部分原因是因?yàn)樾枰洃洿罅康?b class='flag-5'>命令,畢竟掌握命令是高效使用命令行的前提不幸的是,學(xué)習(xí)這些命令并無捷徑,
    發(fā)表于 07-25 08:10

    caxa命令行中的應(yīng)用

    caxa命令行中的應(yīng)用 命令行對(duì)于大多用戶來說往往只是輸入數(shù)據(jù)的作用,但是其中的奧妙還有很多,下面就給大家
    發(fā)表于 10-18 18:18 ?2407次閱讀

    CMD的命令行高級(jí)教程

    CMD的命令行高級(jí)教程
    發(fā)表于 10-24 08:31 ?30次下載
    CMD的<b class='flag-5'>命令行</b>高級(jí)教程

    監(jiān)控jvm常用的5個(gè)命令行工具

    常用的幾個(gè)命令行工具有jps、jstat、jinfo、jmap、jstack等。這幾個(gè)工具可以安裝openjdk-devel-debug包。
    的頭像 發(fā)表于 02-06 14:47 ?6105次閱讀
    監(jiān)控jvm常用的5<b class='flag-5'>個(gè)</b><b class='flag-5'>命令行</b><b class='flag-5'>工具</b>

    實(shí)用 Linux 命令行使用技巧集錦

    下面介紹的都是命令行工具,這些工具在日常工作中都很有用。
    的頭像 發(fā)表于 03-21 14:42 ?4993次閱讀

    Xilinx軟件命令行工具:XSCT開發(fā)和調(diào)試

    了解如何使用XSCT,Xilinx軟件命令行工具進(jìn)行開發(fā)和調(diào)試。 該視頻演示了XSCT如何充當(dāng)Xilinx SDK的命令行控制臺(tái)。
    的頭像 發(fā)表于 11-21 06:02 ?1.5w次閱讀

    Xilinx軟件命令行工具進(jìn)行開發(fā)和調(diào)試

    了解如何使用XSCT,Xilinx軟件命令行工具進(jìn)行開發(fā)和調(diào)試。 該視頻演示了XSCT如何充當(dāng)Xilinx SDK的命令行控制臺(tái)。
    的頭像 發(fā)表于 11-22 06:53 ?7098次閱讀

    Git常見的誤區(qū)和命令行工具等綜述

    Git常見的誤區(qū)和命令行工具等綜述
    發(fā)表于 08-31 09:51 ?0次下載

    mini shell命令行調(diào)試工具(單片機(jī)、c語言)

    @mini shell命令行調(diào)試工具介紹Mini shell 命令行調(diào)試工具(單片機(jī)、c語言)Mini shell是
    發(fā)表于 11-29 10:21 ?10次下載
    mini shell<b class='flag-5'>命令行</b>調(diào)試<b class='flag-5'>工具</b>(單片機(jī)、c語言)

    新的開源命令行工具west

    電子發(fā)燒友網(wǎng)站提供《新的開源命令行工具west.zip》資料免費(fèi)下載
    發(fā)表于 11-11 09:25 ?0次下載
    新的開源<b class='flag-5'>命令行</b><b class='flag-5'>工具</b>west

    介紹Go里面經(jīng)常使用到的命令行工具

    優(yōu)秀的工具配合熟練的使用,往往可以讓開發(fā)效率大幅度提升,本小節(jié)介紹 Go 里面經(jīng)常使用到的命令行工具
    的頭像 發(fā)表于 05-22 16:58 ?1551次閱讀
    介紹Go里面經(jīng)常使用到的<b class='flag-5'>命令行</b><b class='flag-5'>工具</b>

    PetaLinux工具文檔:命令行參考指南

    電子發(fā)燒友網(wǎng)站提供《PetaLinux工具文檔:命令行參考指南.pdf》資料免費(fèi)下載
    發(fā)表于 09-15 14:52 ?0次下載
    PetaLinux<b class='flag-5'>工具</b>文檔:<b class='flag-5'>命令行</b>參考指南

    個(gè)開源MCU級(jí)的命令行交互組件

    個(gè)開源MCU級(jí)命令行交互組件~
    的頭像 發(fā)表于 10-17 16:26 ?642次閱讀
    <b class='flag-5'>一</b><b class='flag-5'>個(gè)</b>開源MCU級(jí)的<b class='flag-5'>命令行</b>交互組件

    HarmonyOS開發(fā):【基于命令行(安裝工具集)】

    使用命令行進(jìn)行設(shè)備開發(fā)時(shí),可以通過以下步驟安裝編譯OpenHarmony需要的工具
    的頭像 發(fā)表于 04-25 21:03 ?734次閱讀
    HarmonyOS開發(fā):【基于<b class='flag-5'>命令行</b>(安裝<b class='flag-5'>庫</b>和<b class='flag-5'>工具</b>集)】
    主站蜘蛛池模板: 欧美黑人巨大xxxxx | www色视频在线观看 WWW色视频片内射 | 出差无套内射小秘书 | 青青久在线视频免费观看 | 亚洲精品国偷拍自产在线观看蜜臀 | 99精品观看 | 最近2019年日本中文免费字幕 | 蜜桃成熟时33D在线嘟嘟网 | 国产真实女人一级毛片 | 中字幕视频在线永久在线 | 国产在线观看成人免费视频 | 蜜臀AV精品一区二区三区 | 欧美内射深插日本少妇 | 啊灬啊灬啊灬快高潮视频 | 极品少妇高潮啪啪AV无码吴梦梦 | av影音先锋天堂网 | 国产高清精品国语特黄A片 国产高清国内精品福利色噜噜 | 成人网站国产在线视频内射视频 | 欧美一区二区日韩一区二区 | 老师的快感电影完整版 | 国产AV国产精品国产三级在线L | 另类重口bdsm日本tv | 新版孕妇bbwbbwbbw | 久久伊人中文字幕有码 | 奇米狠狠干| 入禽太深视频免费视频 | 青青热久精品国产亚洲AV无码 | 午理论理影片被窝 | 免费观看久久 | 国产午夜伦鲁鲁 | SM双性精跪趴灌憋尿调教H | 国产自产视频在线观看香蕉 | 国产午夜精品理论片影院 | 国产欧美一区二区三区久久 | H狠狠躁死你H | 免费女人光着全身网站 | 国产精品三级在线观看 | 色欲久久99精品久久久久久AV | free高跟丝袜秘书hd | 涩涩999 | 欧美一区二区三区不卡免费 |

    電子發(fā)燒友

    中國電子工程師最喜歡的網(wǎng)站

    • 2931785位工程師會(huì)員交流學(xué)習(xí)
    • 獲取您個(gè)性化的科技前沿技術(shù)信息
    • 參加活動(dòng)獲取豐厚的禮品