## 解析命令行flag標識
使用flag包可以輕松地將命令行標識參數添加到Go應用程序。它有一些缺點——你往往需要復制很多代碼以添加簡寫版本的標志,并且它們是按幫助提示的字母順序排序的。 有許多第三方庫試圖解決這些缺點,但本章將重點關注標準庫版本而不是那些第三方庫。
### 實踐
1. 創建flags.go:
```
package main
import (
"flag"
"fmt"
)
// Config存儲接收到的標識
type Config struct {
subject string
isAwesome bool
howAwesome int
countTheWays CountTheWays
}
// Setup 根據傳入的標識初始化配置
func (c *Config) Setup() {
// 你可以使用這樣的方式直接初始化標識:
// var someVar = flag.String("flag_name", "default_val", "description")
// 但在實際操作中使用結構體來承載會更好一些
// 完整版
flag.StringVar(&c.subject, "subject", "", "subject is a string, it defaults to empty")
// 簡寫版
flag.StringVar(&c.subject, "s", "", "subject is a string, it defaults to empty (shorthand)")
flag.BoolVar(&c.isAwesome, "isawesome", false, "is it awesome or what?")
flag.IntVar(&c.howAwesome, "howawesome", 10, "how awesome out of 10?")
// 自定義變量類型
flag.Var(&c.countTheWays, "c", "comma separated list of integers")
}
// GetMessage 將所有的內部字段拼接成完整的句子
func (c *Config) GetMessage() string {
msg := c.subject
if c.isAwesome {
msg += " is awesome"
} else {
msg += " is NOT awesome"
}
msg = fmt.Sprintf("%s with a certainty of %d out of 10. Let me count the ways %s", msg, c.howAwesome, c.countTheWays.String())
return msg
}
```
2. 建立custom.go:
```
package main
import (
"fmt"
"strconv"
"strings"
)
// CountTheWays使一個自定義變量類型
// 我們會從標識中讀取到它
type CountTheWays []int
// 想要實現自定義類型的flag 必須實現flag.Value接口
// 該接口包含了
// String() string
// Set(string) error
func (c *CountTheWays) String() string {
result := ""
for _, v := range *c {
if len(result) > 0 {
result += " ... "
}
result += fmt.Sprint(v)
}
return result
}
func (c *CountTheWays) Set(value string) error {
values := strings.Split(value, ",")
for _, v := range values {
i, err := strconv.Atoi(v)
if err != nil {
return err
}
*c = append(*c, i)
}
return nil
}
```
3. 建立main.go:
```
package main
import (
"flag"
"fmt"
)
func main() {
// 初始化
c := Config{}
c.Setup()
// 常見的調用方式
flag.Parse()
// 將通過命令行輸入的flag標識拼接打印
fmt.Println(c.GetMessage())
}
```
4. 將main.go打包為flags,運行會顯示:
```
is NOT awesome with a certainty of 10 out of 10. Let me count the ways
```
5. 運行./flags -s會顯示:
```
flag needs an argument: -s
Usage of ./flags:
-c value
comma separated list of integers
-howawesome int
how awesome out of 10? (default 10)
-isawesome
is it awesome or what?
-s string
subject is a string, it defaults to empty (shorthand)
-subject string
subject is a string, it defaults to empty
```
6. 運行./flags -c 1,2,3 -s aaa會顯示:
```
aaa is NOT awesome with a certainty of 10 out of 10. Let me count the ways 1 ... 2 ... 3
```
### 說明
本節演示了flag包的大多數常見用法。涉及對自定義變量類型,各種內置變量,長短標識以及結構映射標識的使用。我們需要main函數以調用flag.Parse()。
在這個示例中你會發現能夠自動獲取-h以顯示包含的標識列表。需要注意的是,可以在沒有參數的情況下調用的布爾標識,并且標識的順序無關緊要。
flag包提供了快速構建命令行應用的方法,在工作中我們可以利用其來指定設置日志級別或根據應用程序的需求引導用戶輸入。在命令行參數章節中,我們將探索標識集并使用參數在它們之間切換。
* * * *
學識淺薄,錯誤在所難免。歡迎在群中就本書提出修改意見,以饗后來者,長風拜謝。
Golang中國(211938256)
beego實戰(258969317)
Go實踐(386056972)
- 前言
- 第一章 I/O和文件系統
- 常見 I/O 接口
- 使用bytes和strings包
- 操作文件夾和文件
- 使用CSV格式化數據
- 操作臨時文件
- 使用 text/template和HTML/templates包
- 第二章 命令行工具
- 解析命令行flag標識
- 解析命令行參數
- 讀取和設置環境變量
- 操作TOML,YAML和JSON配置文件
- 操做Unix系統下的pipe管道
- 處理信號量
- ANSI命令行著色
- 第三章 數據類型轉換和解析
- 數據類型和接口轉換
- 使用math包和math/big包處理數字類型
- 貨幣轉換和float64注意事項
- 使用指針和SQL Null類型進行編碼和解碼
- 對Go數據編碼和解碼
- Go中的結構體標簽和反射
- 通過閉包實現集合操作
- 第四章 錯誤處理
- 錯誤接口
- 使用第三方errors包
- 使用log包記錄錯誤
- 結構化日志記錄
- 使用context包進行日志記錄
- 使用包級全局變量
- 處理恐慌
- 第五章 數據存儲
- 使用database/sql包操作MySQL
- 執行數據庫事務接口
- SQL的連接池速率限制和超時
- 操作Redis
- 操作MongoDB
- 創建存儲接口以實現數據可移植性
- 第六章 Web客戶端和APIs
- 使用http.Client
- 調用REST API
- 并發操作客戶端請求
- 使用OAuth2
- 實現OAuth2令牌存儲接口
- 封裝http請求客戶端
- 理解GRPC的使用
- 第七章 網絡服務
- 處理Web請求
- 使用閉包進行狀態處理
- 請求參數驗證
- 內容渲染
- 使用中間件
- 構建反向代理
- 將GRPC導出為JSON API
- 第八章 測試
- 使用標準庫進行模擬
- 使用Mockgen包
- 使用表驅動測試
- 使用第三方測試工具
- 模糊測試
- 行為驅動測試
- 第九章 并發和并行
- 第十章 分布式系統
- 第十一章 響應式編程和數據流
- 第十二章 無服務器編程
- 第十三章 性能改進