- 深入淺出Go語言核心編程
- 張朝明 李奕鋒 甘海彬
- 1875字
- 2024-12-24 10:23:12
1.7 編程范例——啟動參數的使用
在前面的內容中,我們講述了開發環境的搭建,以及運行第一個實例程序,本節將通過實例——啟動參數的使用來進一步熟悉Go語言程序的基本編寫過程。
1.7.1 程序啟動的入口函數
在1.4.2節的代碼清單1-1中的包名和函數名均為main。對于一個Go程序的入口文件,其包名必須為main。例如,將代碼清單1-1中的包名修改為demo:

在修改后的代碼中,包名由main修改為了demo,此時無論是在GoLand直接利用菜單命令運行,還是在命令行使用go run命令,均無法正常運行,如下所示。
$ go run 1-1.go package command-line-arguments is not a main package
但是文件1-1.go的編譯是可以順利通過的,這是因為此時的函數的完整引用名稱為demo.main(),編譯器只是將它視作一個普通函數,而非程序的執行入口。
同樣地,函數名main也是一個程序必需的,不能修改為其他名稱,否則程序也將無法成功執行。例如,將函數名main修改為demo,并嘗試使用go run命令運行,輸出結果如下:
$ go run 1-1.go # command-line-arguments runtime.main_main·f: function main is undeclared in the main package
因此,我們可以總結出,即使一個最簡單的Go語言程序,函數main.main()是其入口的唯一標識,存在且只能存在一個main.main()函數。
1.7.2 獲取啟動參數
許多編程語言在程序入口函數中有參數定義,用于接收啟動時的個性化參數。例如,Java語言的參數接收方式有其固定格式:
public static void main(String[] args){ }
其中,參數args是一個String類型的數組。該參數按照順序接收命令行傳遞的參數。但是,Go語言使用了完全不同的策略——并沒有顯式的參數定義(例如前面的main.main()函數的定義中就沒有任何參數定義),而是使用固定函數來獲取命令行參數。
1.os.Args變量
os.Args是os包中定義的全局變量,其作用類似于Java語言main()方法中的args參數,其源碼定義如下:
var Args []string
該變量是一個string類型的切片。當運行Go程序時,可以增加參數選項,這些參數將會被自動捕獲并填充到全局變量os.Args中。如此一來,我們便可以在程序中針對os.Args進行處理。代碼清單1-2演示了這一用法。
代碼清單1-2 利用os.Args變量獲取命令行參數

代碼解析:
(1)for i, arg := range os.Args,用于循環處理os.Args中的所有參數,其中變量i代表了每個參數的索引值,arg代表具體參數。
(2)fmt.Printf("參數%d = %s\n", i, arg),用于打印每個參數的索引和具體參數內容。Printf中的f代表Format,意為按一定格式打印;其中的%d和%s均為占位符,分別代表了數值格式和字符串格式。
可以利用如下命令進行測試:
$ go run 1-2.go a b c
其中,go run 1-2.go為我們常用的運行命令,其后的a、b、c為附加參數,多個附加參數之間利用空格分隔。
該命令執行后,控制臺的輸出如下:

在輸出中,參數0為編譯后可執行文件的絕對路徑,無論有沒有附加參數,參數0都是默認存在的。顯式附加的參數a、b、c分別對應了參數1、參數2、參數3。
利用os.Args全局變量可以獲得附加參數列表,但是這種形式下,只能通過參數位置進行捕獲,這就非常依賴于參數順序的正確性。
2.os.Flag()函數
除了os.Args外,還可以利用flag.Int()、flag.Bool()、flag.String()等一系列os.Flag()函數來獲得參數。與os.Args依賴位置不同,os.Flag()函數可以按參數名獲得參數。代碼清單1-3演示了這一用法。
代碼清單1-3 利用os.Flag()函數獲得命令行參數

代碼解析:
(1)flag.Int("intVal", 0, "int類型參數"):用于獲取名為“intVal”的參數。flag.Int()會將參數視作int類型。其中的0代表如果參數未指定,則使用默認值0。
(2)類似地,flag.Bool("boolVal", false, "bool類型參數")和flag.String("stringVal", "", "string類型參數")分別用于獲得名為“boolVal”和“stringVal”的參數,其數據類型分別為布爾型和字符串類型。
(3)flag.Parse()是必需的步驟,用于解析以上參數。
如果在未指定任何參數的情況下運行該代碼段,將只輸出默認值,如下所示。
$ go run 1-3.go -intVal: 0 -boolVal: false -stringVal:
指定參數的命令也非常簡單,其使用格式如下:
go run main.go -argName1 argVal1 -argName2 argVal2 ...
其中參數名(argName)和參數值(argVal)成對出現,例如-argName1 argVal1 -argName2 argVal2等。需要注意的是參數名之前的中畫線(-)不可省略。
可以利用如下命令執行1-3.go,并傳遞intVal、boolVal和stringVal參數的值:
$ go run 1-3.go -intVal 15 -boolVal -stringVal dev
在控制臺上的輸出如下:
-intVal: 15 -boolVal: true -stringVal: dev
可以看到,三個參數均已成功獲取到指定值。其中稍微有點特殊的是布爾類型的獲取,如果我們像其他參數形式一樣使用argName+argVal的形式,會發現其后的stringVal無法成功捕獲,如下所示。
$ go run 1-3.go -intVal 15 -boolVal true -stringVal dev -intVal: 15 -boolVal: true -stringVal:
在輸出內容中,strintVal的值為空字符,即默認值。這是因為參數-boolVal true雖然在形式上與其他參數保持了一致性,但是對于布爾型參數解析(flag.Bool),單獨的“-boolVal”會被識別為一個參數;繼續解析時,會嘗試將“true”識別為參數名。但是,參數名必須要以“-”開頭,所以“true”被識別為非法的參數名,導致解析終止,后續字符串“-stringVal dev”的解析被忽略。
3.命令行參數的最優寫法
Go程序指定命令行參數時有以下4種形式可供選擇:
-arg value
--arg value
-arg=value
--arg=value
但是布爾類型比較特殊,只以下支持兩種形式:
-arg
-arg=value
因此,為了統一格式和避免不必要的問題,在使用命令行傳遞參數時,推薦使用-arg=value。調用代碼清單1-3的命令,使用如下形式是最佳選擇:
$ go run 1-3.go -intVal=15 -boolVal=true -stringVal=dev -intVal: 15 -boolVal: true -stringVal: dev
- 流量的秘密:Google Analytics網站分析與優化技巧(第2版)
- Computer Vision for the Web
- NLTK基礎教程:用NLTK和Python庫構建機器學習應用
- 編程珠璣(續)
- 編寫高質量代碼:改善Python程序的91個建議
- HTML5+CSS3網站設計教程
- Python數據分析(第2版)
- Learning Network Forensics
- The HTML and CSS Workshop
- Mastering Ext JS
- QGIS By Example
- Learning OpenStack Networking(Neutron)
- Protocol-Oriented Programming with Swift
- 深入淺出React和Redux
- Machine Learning With Go