咱們隨便寫一個平常使用的psql的命令行用法
html
1.
manu@manu-hacks:~$ pg_ctl -D /home/manu/DB_data/ -l /home/manu/DB_data/postgres_manu.
log
start
post
2.
server starting
spa
這種狀況下咱們更須要的是解析各個參數的意義,好比-D選項 是通知pg_ctl pgdata的路徑在那,-l選項告知的是log記錄到那個文件,start至關於子命令,告知action。對於這種命令,咱們都知道C語言有getopt及其getopt_long來解決。go語言怎麼解決?
go語言提供了flag這個package。來應對這種入參的解析。
flag支持的語言格式以下:.net
-flag // bool類型only
-flag=x
-flag x //not bool 類型
很天然,這個flag可以解析 -D /home/manu/DB_data,對應第二種類型,咱們知道pg_ctl有-W選項,屬於一個開關性質的bool型的選項命令行
1.
-W
do
not wait
until
operation completes
server
天然對應第一種類型,也能夠解析。第二種也很好理解。
下面我給出一個例子,簡單的解析這個pg_ctl的命令:
htm
01.
manu@manu-hacks:~/code/go/self$ cat pg_ctl_parse.go
02.
03.
04.
package main
05.
import (
06.
"fmt"
07.
"flag"
08.
)
09.
10.
func main(){
11.
12.
data_path := flag.String(
"D"
,
"/home/manu/sample/"
,
"DB data path"
)
13.
log_file := flag.String(
"l"
,
"/home/manu/sample.log"
,
"log file"
)
14.
nowait_flag :=flag.Bool(
"W"
,
false
,
"do not wait until operation completes"
)
15.
16.
flag.Parse()
17.
18.
var cmd string = flag.Arg(0);
19.
20.
fmt.Printf(
"action : %s\n"
,cmd)
21.
fmt.Printf(
"data path: %s\n"
,*data_path)
22.
fmt.Printf(
"log file : %s\n"
,*log_file)
23.
fmt.Printf(
"nowait : %v\n"
,*nowait_flag)
24.
25.
fmt.Printf(
"-------------------------------------------------------\n"
)
26.
27.
fmt.Printf(
"there are %d non-flag input param\n"
,flag.NArg())
28.
for
i,param := range flag.Args(){
29.
fmt.Printf(
"#%d :%s\n"
,i,param)
30.
}
31.
32.
33.
}
OK,咱們分析下代碼(分割線下面的咱們暫時不看):
第一行對應的是data_path的解析規則
-D選項對應的值是字符串類型字符串,
默認值是「/home/manu/sample」,
DB data path提示信息或者help信息或者說明是。
01.
manu@manu-hacks:~/code/go/self$ go run pg_ctl_parse.go -D /home/manu/DB_data/ -l /home/manu/DB_data/postgres_manu.log -W start
02.
action : start
03.
data path: /home/manu/DB_data/
04.
log
file
: /home/manu/DB_data/postgres_manu.log
05.
nowait :
true
06.
-------------------------------------------------------
07.
there are 1 non-flag input param
08.
#0 :start
09.
10.
manu@manu-hacks:~/code/go/self$ go run pg_ctl_parse.go -l=/home/manu/DB_data/postgres_manu.log -W -D /home/manu/DB_data/ start
11.
action : start
12.
data path: /home/manu/DB_data/
13.
log
file
: /home/manu/DB_data/postgres_manu.log
14.
nowait :
true
15.
-------------------------------------------------------
16.
there are 1 non-flag input param
17.
#0 :start
咱們看到了,解析出了data_path,log_file不管 -l -D出現的順序如何,只要正常的出現了,就能正常的解析。
可是晴朗的天空中也有一片烏雲,start不是這種 -key=alue 或則-option的類型,flag是解析不了的。咱們稱這種參數爲non-flag參數,flag解析遇到non-flag參數就中止了:
1.
s := f.args[0]
2.
if
len(s) == 0 || s[0] !=
'-'
|| len(s) == 1 {
3.
return
false
, nil
4.
}
因此若是咱們將non-flag參數放在最前面,flag什麼也不會解析,由於flag遇到了這個就中止解析了。
01.
manu@manu-hacks:~/code/go/self$ go run pg_ctl_parse.go start -l=/home/manu/DB_data/postgres_manu.log -W -D /home/manu/DB_data/
02.
action : start
03.
data path: /home/manu/sample
04.
log
file
: /home/manu/sample.log
05.
nowait :
false
06.
-------------------------------------------------------
07.
there are 5 non-flag input param
08.
#0 :start
09.
#1 :-l=/home/manu/DB_data/postgres_manu.log
10.
#2 :-W
11.
#3 :-D
12.
#4 :/home/manu/DB_data/
OK,flag提供了Arg(i),Args()來獲取non-flag參數,NArg()來獲取non-flag的個數。正如咱們們sample 代碼看到的。
1.
fmt.Printf(
"there are %d non-flag input param\n"
,flag.NArg())
2.
for
i,param := range flag.Args(){
3.
fmt.Printf(
"#%d :%s\n"
,i,param)
4.
}
flag還提供了NFlag()獲取那些匹配上的參數的個數。 從例子上看,flag package頗有用,可是並無強大到解析一切的程度。 若是你有相似-option或者-key =value這種參數,不妨試試 flag。若是你的入參解析很是複雜,flag可能捉襟見肘。