Go語言
Go(又稱Golang)是Google開發的一種靜態強類型、編譯型、并發型,并具有垃圾回收功能的編程語言。
羅伯特·格瑞史莫(Robert Griesemer),羅勃·派克(Rob Pike)及肯·湯普遜(Ken Thompson)于2007年9月開始設計Go,稍后Ian Lance Taylor、Russ Cox加入項目。Go是基于Inferno操作系統所開發的。Go于2009年11月正式宣布推出,成為開放源代碼項目,并在Linux及Mac OS X平臺上進行了實現,后來追加了Windows系統下的實現。在2016年,Go被軟件評價公司TIOBE 選為“TIOBE 2016 年最佳語言”。 目前,Go每半年發布一個二級版本(即從a.x升級到a.y)。
CLI
CLI是Command Line Interface的縮寫,即 命令行界面。CLI界面是所有 路由器、TM (Termination Multiplexer, 終端復用器)、CM(Cable Modem, 電纜調制解調器)等產品提供的界面,如 CISCO, LUCENT,Arris, 華為等。它是 路由器產品的標準。使用CLI具有使用要求低(只需要 串行口),容易使用,功能擴充方便等優點,特別是當有很多(如10臺)臺 路由器設備需要配置的時候,可以通過COPY/PASTE功能很快完成所有路由器的配置。不需要通過IE一臺臺配置。
在這篇博文中,我們將用 Go 構建一個 CLI 應用程序,我們暫且把它叫做 go-grab-xkcd. 該應用程序從 XKCD 拉取漫畫并通過命令行參數為您提供各種操作選項.
我們將僅使用 Go 標準庫構建整個應用程序而不使用外部依賴.
這個應用程序的想法或許看起來有點秀逗,但目的是實踐用 Go 編寫生產級別的 (某種) 代碼而不是想被 Google 收購.
最后還有一個額外獎勵
讓我們先來運行一下這個應用程序,然后再進行操作
$ go-grab-xkcd --help
Usage of go-grab-xkcd:
-n int
Comic number to fetch (default latest)
-o string
Print output in format: text/json (default "text")
-s Save image to current directory
-t int
Client timeout in seconds (default 30)
$ go-grab-xkcd -n 323
Title: Ballmer Peak
Comic No: 323
Date: 1-10-2007
Description: Apple uses automated schnapps IVs.
Image: https://imgs.xkcd.com/comics/ballmer_peak.png
$ go-grab-xkcd -n 323 -o json
{
"title": "Ballmer Peak",
"number": 323,
"date": "1-10-2007",
"description": "Apple uses automated schnapps IVs.",
"image": "https://imgs.xkcd.com/comics/ballmer_peak.png"
}你可以通過下載并運行計算機上的應用程序來嘗試其他選項.
本教程結束后你將熟悉以下主題內容:
接收命令行參數
JSON 和 Go 結構體之間的相互轉換
進行 API 調用
創建文件 (從網絡上下載并保存)
字符串操作
以下是項目結構
$ tree go-grab-xkcd
go-grab-xkcd
├── client
│ └── xkcd.go
└── model
└── comic.go
├── main.go
└── go.mod
go.mod - Go Modules file used in Go for package management
main.go - Main entrypoint of the application
comic.go - Go representation of the data as a struct and operations on it
xkcd.go - xkcd client for making HTTP calls to the API, parsing response and saving to disk1: 初始化項目
創建一個 go.mod 文件 -
$ go mod init
這將會有助于你進行包管理 (思考 JS 中的 package.json 文件)。
2: xkcd API
xkcd 是令人稱贊的,您不需要任何注冊或訪問密鑰就可以使用它們的 API。 打開 xkcd API “文檔” 您將會發現有兩個端點 -
http://xkcd.com/info.0.json - 獲取最新漫畫
http://xkcd.com/614/info.0.json - 通過漫畫編號獲取指定的漫畫
以下是這些端點的 JSON 響應 -
{
"num": 2311,
"month": "5",
"day": "25",
"year": "2020",
"title": "Confidence Interval",
"alt": "The worst part is that's the millisigma interval.",
"img": "https://imgs.xkcd.com/comics/confidence_interval.png",
"safe_title": "Confidence Interval",
"link": "",
"news": "",
"transcript": ""
}文章相關 xkcd
2: 為漫畫創建模型
根據上述 JSON 響應,我們在 model 包中的 comic.go 中創建一個叫做 ComicResponse 的 struct
type ComicResponse struct {
Month string `json:"month"`
Num int `json:"num"`
Link string `json:"link"`
Year string `json:"year"`
News string `json:"news"`
SafeTitle string `json:"safe_title"`
Transcript string `json:"transcript"`
Alt string `json:"alt"`
Img string `json:"img"`
Title string `json:"title"`
Day string `json:"day"`
}您可以使用 JSON-to-Go 工具從 JSON 自動生成結構體.
順便創建另一個結構體,該結構體將用于從我們的應用程序輸出數據.
type Comic struct {
Title string `json:"title"`
Number int `json:"number"`
Date string `json:"date"`
Description string `json:"description"`
Image string `json:"image"`
}將以下兩種方法添加到 ComicResponse 結構體
// FormattedDate 函數將格式化日期元素為一個字符串
func (cr ComicResponse) FormattedDate() string {
return fmt.Sprintf("%s-%s-%s", cr.Day, cr.Month, cr.Year)
}
// Comic 函數將從 API 接收到的 ComicResponse 轉換為應用程序的輸出格式, Comic 結構體
func (cr ComicResponse) Comic() Comic {
return Comic{
Title: cr.Title,
Number: cr.Num,
Date: cr.FormattedDate(),
Description: cr.Alt,
Image: cr.Img,
}
}然后將以下兩種方法添加到 Comic 結構體
// PrettyString 函數創建一個漂亮的 Comic 字符串并用于輸出
func (c Comic) PrettyString() string {
p := fmt.Sprintf(
"Title: %s\nComic No: %d\nDate: %s\nDescription: %s\nImage: %s\n",
c.Title, c.Number, c.Date, c.Description, c.Image)
return p
}
// JSON 函數將 Comic 結構體轉換為 JSON, 我們將使用 JSON 字符串作為輸出內容
func (c Comic) JSON() string {
cJSON, err := json.Marshal(c)
if err != nil {
return ""
}
return string(cJSON)
}3: 設置 xkcd 客戶端發起請求,解析響應并保存到磁盤
在 client 包中創建 xkcd.go 文件.
首先定義一個叫做 ComicNumber 自定義類型,數據類型為 int
type ComicNumber int
定義常量
const (
// xkcd 的 BaseURL
BaseURL string = "https://xkcd.com"
// DefaultClientTimeout 是取消請求之前要等待的時間
DefaultClientTimeout time.Duration = 30 * time.Second
// 根據 xkcd API, LatestComic 是最新的漫畫編號
LatestComic ComicNumber = 0
)創建一個結構體 XKCDClient, 它將用于向 API 發出請求.
// XKCDClient 是 XKCD 的客戶端結構體
type XKCDClient struct {
client *http.Client
baseURL string
}
// NewXKCDClient 創建一個新的 XKCDClient
func NewXKCDClient() *XKCDClient {
return &XKCDClient{
client: &http.Client{
Timeout: DefaultClientTimeout,
},
baseURL: BaseURL,
}
}添加以下 4 種方法到 XKCDClient
SetTimeout()
// SetTimeout 重寫了默認的 ClientTimeout
func (hc *XKCDClient) SetTimeout(d time.Duration) {
hc.client.Timeout = d
}Fetch()
// Fetch 根據提供的漫畫編號檢索漫畫
func (hc *XKCDClient) Fetch(n ComicNumber, save bool) (model.Comic, error) {
resp, err := hc.client.Get(hc.buildURL(n))
if err != nil {
return model.Comic{}, err
}
defer resp.Body.Close()
var comicResp model.ComicResponse
if err := json.NewDecoder(resp.Body).Decode(&comicResp); err != nil {
return model.Comic{}, err
}
if save {
if err := hc.SaveToDisk(comicResp.Img, "."); err != nil {
fmt.Println("Failed to save image!")
}
}
return comicResp.Comic(), nil
}SaveToDisk()
// SaveToDisk 下載并保存漫畫到本地磁盤
func (hc *XKCDClient) SaveToDisk(url, savePath string) error {
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
absSavePath, _ := filepath.Abs(savePath)
filePath := fmt.Sprintf("%s/%s", absSavePath, path.Base(url))
file, err := os.Create(filePath)
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(file, resp.Body)
if err != nil {
return err
}
return nil
}buildURL()
func (hc *XKCDClient) buildURL(n ComicNumber) string {
var finalURL string
if n == LatestComic {
finalURL = fmt.Sprintf("%s/info.0.json", hc.baseURL)
} else {
finalURL = fmt.Sprintf("%s/%d/info.0.json", hc.baseURL, n)
}
return finalURL
}4: 連接所有
在 main() 函數內部我們鏈接了所有內容
讀取命令行參數
實例化 XKCDClient
使用 XKCDClient 從 API 拉取數據
輸出
讀取命令行參數
comicNo := flag.Int(
"n", int(client.LatestComic), "Comic number to fetch (default latest)",
)
clientTimeout := flag.Int64(
"t", int64(client.DefaultClientTimeout.Seconds()), "Client timeout in seconds",
)
saveImage := flag.Bool(
"s", false, "Save image to current directory",
)
outputType := flag.String(
"o", "text", "Print output in format: text/json",
)flag.Parse()
實例化 XKCDClient
xkcdClient := client.NewXKCDClient() xkcdClient.SetTimeout(time.Duration(*clientTimeout) * time.Second)
使用 XKCDClient 從 API 拉取數據
comic, err := xkcdClient.Fetch(client.ComicNumber(*comicNo), *saveImage)
if err != nil {
log.Println(err)
}輸出
if *outputType == "json" {
fmt.Println(comic.JSON())
} else {
fmt.Println(comic.PrettyString())
}程序運行如下
$ go run main.go -n 323 -o json
或者將其構建為你的筆記本電腦的二進制可執行文件并運行它
$ go build . $ ./go-grab-xkcd -n 323 -s -o json
可以在這個 Github 倉庫找到完整的源代碼 - go-grab-xkcd
額外獎勵
通過使用這個簡單的 shell 魔術工具可以依次下載多個漫畫
$ for i in {1..10}; do ./go-grab-xkcd -n $i -s; done;上面的 shell 代碼簡單地在 for 循環中調用 go-grab-xkcd 命令,由于 xkcd 使用序列整數,因此將 i 值替換為漫畫編號作為漫畫編號 / ID.
以上就是使用 Go 來構建一個 CLI 程序的詳細內容,更多請關注億速云其它相關文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。