官术网_书友最值得收藏!

1.4 第一個Go程序

上面對Go語言的特性進行了介紹,并從頭開始搭建Go語言的開發環境。當Go語言開發環境配置完成后,我們就可以著手編寫第一個Go程序了。根據慣例,這里給出一個最基本的Go程序,輸出字符串“Hello World”。

為了提高編程效率,編寫Go程序,一般來說都需要借助集成開發工具。這里我們先用Windows的“記事本”來編寫,并用go build命令來編譯Go程序。

1.4.1 搭建本書項目代碼結構

在編寫第一個Go程序之前,首先構建本書的項目代碼結構。頂級目錄為go.introduce,放于%GOPATH%目錄下的src目錄中。在go.introduce目錄中,分別創建各章的子目錄,如chapter01和chapter02。目錄結構如圖1.7所示。

圖1.7 Go項目的目錄結構示意圖

工作區目錄%GOPATH%(C:\GoWork)有3個子目錄:

· src目錄

用于以代碼包的形式組織并保存Go源代碼文件。這里的代碼包與src下的子目錄一一對應。例如,一個源代碼文件被聲明為屬于代碼包logging,那么它就應當被保存在src目錄下名為logging的子目錄中。

· pkg目錄

用于存放經由go install命令構建安裝后的代碼包(包含Go庫源代碼文件)的.a歸檔文件。該目錄與GOROOT目錄下的pkg功能類似。區別在于,工作區中的pkg目錄專門用來存放用戶代碼的歸檔文件。構建和安裝用戶源代碼的過程一般會以代碼包為單位進行,比如mylog包被編譯安裝后,將生成一個名為mylog.a的歸檔文件,并存放在當前工作區的pkg目錄下的平臺相關目錄中。

· bin目錄

與pkg目錄類似,在通過go install命令完成安裝后,保存由Go命令源代碼文件生成的可執行文件。

說明

在Linux操作系統下,這個可執行文件一般是一個與源代碼文件同名的文件。在Windows操作系統下,這個可執行文件的名稱是源代碼文件名稱加.exe后綴。

1.4.2 創建并運行第一個Go程序

新建一個hello.go文本文件,并用“記事本”程序打開,編寫腳本,參考示例程序1-1。

示例程序1-1 第一個Go程序:chapter01\code01\hello.go

每一個可獨立運行的Go程序必定包含一個packagemain,在這個main包中必定包含一個入口函數main,而這個函數既沒有參數也沒有返回值。

Go語言的函數定義用關鍵詞func進行定義。其中,import關鍵詞用于導入包,由于第05行用到了fmt包中的Println方法,因此需要在第03行提前導入。fmt包中的Println方法可以將值打印到控制臺中,即輸出“Hello World”字符串。

注意

如果用“記事本”進行編輯,特別是出現中文的情況下,就需要將“記事本”的編碼改成UTF-8,否則編譯文件時會報錯。保存文件名可以是任意名稱,但必須以" .go "后綴結尾。

“記事本”可以用另存為的方式來選擇UTF-8編碼,如圖1.8所示。

圖1.8 “記事本”以另存為的方式選擇文件的UTF-8編碼

在目錄go.introduce\chapter01\code01\中打開“命令提示符”窗口。輸入“go build”命令進行編譯。若編譯成功則會在code01中生成code01.exe文件。如果輸入“go run hello.go”,則會編譯并運行程序,輸出“Hello World”字符串。

如果輸入“go install”,就會編譯成code01.exe,并復制到%GOPATH%\bin目錄下,由于此目錄配置在PATH變量中,因此可以直接調用。例如,輸入“code01”則調用code01.exe程序,輸出“Hello World”字符串,如圖1.9所示。

圖1.9 GO編譯命令

注意

go install能生成包,而go build不能生成包。

1.4.3 Go程序的編譯

在Go語言1.9版本之后,默認情況下,Go的編譯器會利用并發特性進行并發編譯,這樣可以充分利用多核的優勢,因此編譯速度非???。go build命令在源代碼編譯過程中會根據源代碼的依賴情況自動編譯源代碼依賴的包,并鏈接生成一個完整的文件。

go build常用的編譯方法如下:

· 無參數編譯:go build命令后面不跟任何參數,即無參數。首先Go編譯器會在執行命令的當前目錄下搜索*.go源代碼文件,成功編譯后會在當前目錄下生成與當前目錄名同名的文件。

· 指定包名編譯:go build命令后面跟著包名,包名是相對于環境變量%GOPATH%下的src目錄而言的。這種編譯的好處是包內的文件數量的變化不需要調整編譯命令。

· 文件列表編譯:go build命令后面跟著文件名,文件名可以是多個,中間用空格隔開,比如go build main.go sum.go。這種編譯方式對于一個目錄當中有多個包的文件并需要指定文件來編譯是比較適合的,但是需要注意文件列表的順序,不同的文件列表順序會影響編譯結果。

另外,go build命令還有一些參數,下面羅列一些分別進行說明:

· -v:編譯時顯示包名。

· -p n:開啟并發編譯,默認情況下該值為計算機的邏輯核數。

· -a:強制重新構建。

· -n:打印編譯時會用到的所有命令,但不真正執行。

· -x:打印編譯時會用到的所有命令。

· -race:開啟競態檢測,常用于并發模式下的共享變量檢測。

· -o:后接文件名,強制對輸出的文件進行重命名。

· -work:打印編譯工作的臨時目錄。

· -gcflags:后面的參數可以是多個,用空格進行分隔,并用""進行包裹,這些參數將傳遞到go tool compile工具中進行調用。例如,go build -gcflags "-l -m"。

· -ldflags:后面的參數可以是多個,用空格進行分隔,并用""進行包裹,這些參數將傳遞到go tool link工具中進行調用。例如,go build -ldflags "-w -s"。這個命令可以隱藏所有代碼實現相關的信息,并減少生成文件的大小。其中,-w可以移除調試信息(無法使用gdb調試),-s可以移除符號表。

Go支持交叉編譯,比如我們在Windows操作系統上進行開發,但是需要部署到Linux操作系統上,由于不同操作系統的底層實現有差異,因此為了更好地提升性能,可以在Windows操作系統上通過配置環境變量來生成Linux操作系統下的文件。例如,在Windows操作系統的命令窗口執行:

set GOOS=linux
set GOARCH=amd64
go build -o linux-main

1.4.4 Go的幫助系統

我們學習任何一種語言都可以參考其內置的幫助系統。Go語言也不例外,打開“命令提示符”窗口,輸入“go help”后按Enter鍵,則會顯示go相關命令,如圖1.10所示。

圖1.10 go help幫助信息

從圖1.10中可以看出,go可以支持的命令有bug、build、clean、doc、env、fmt、generate、install、test、get、run、tool和vet等。下面重點介紹幾個。

(1)fmt可以用gofmt對源代碼進行格式化,這個工具非常有用。我們在提交代碼之前,建議都用這個官方提供的代碼格式化工具對代碼進行格式化,然后提交代碼到Git或者TFS服務器上。

Git或者TFS是分布式版本控制系統,可以實現團隊對于代碼的版本管理工作,防止代碼版本不一致的問題。另外,后面介紹的Go語言代碼編輯器中會用到此工具來格式化代碼,可以說這個工具非常實用,而且可以讓代碼更加規范和優雅。

(2)test命令可以測試包中的函數,其中分為單元(unit)測試和基準(benchmark)測試,單元測試一般驗證函數的正確性,基準測試用于測試性能。test可以指定參數go test -cover來查看測試覆蓋率。測試覆蓋率通過執行某包的測試用例來確認代碼被執行的程度。如果覆蓋率是100%,那么證明單元測試的時候所有的代碼路徑都會執行一遍,如果運行結果都正確,則該函數發生bug的可能性將大大降低。

強烈建議

在命令行中執行go help testflag來查看一些test命令的細節信息,這個命令可以讓我們知道-memprofile、-mutexprofile、-trace和-cpuprofile等參數的作用。

(3)tool命令允許特定的go工具,比如compile工具,我們可以在命令行中輸入go doc cmd/compile來查看具體的說明信息。compile工具的基本用法為:

go tool compile [flags] file...

注意,這個命令的file文件必須是Go源代碼文件,并且屬于同一個包,[flags]參數主要有以下幾個:

· -N:禁止編譯器優化。

· -S:打印匯編語言列表到標準輸出窗口(只打印代碼code部分)。

· -S –S:打印匯編語言列表到標準輸出窗口(只打印代碼code和數據data)。

· -blockprofile file:將編譯期間采樣的block profile信息寫入文件file中。

· -cpuprofile file:將編譯期間采樣的cpu profile信息寫入文件file中。

· -dynlink:實驗特性,允許共享庫引用Go symbols。

· -e:移除錯誤報告的數量限制(默認限制是10)。

· -h:在檢測到第一個錯誤時停止棧跟蹤。

· -l:禁止函數內聯。

· -lang version:設置Go語言的版本。

· -m:打印編譯器的優化策略信息。

· -memprofile file:將編譯期間采樣的memory profile信息寫入文件file中。

· -memprofilerate rate:設置runtime.MemProfileRate的內存采集頻率。

· -mutexprofile file:將編譯期間采樣的mutex profile信息寫入文件file中。

· -race:開啟競爭檢測。

· -traceprofile file:將執行的跟蹤信息execution trace信息寫入文件file中。

go tool compile還有一些參數,這里就不一一闡述了,感興趣的讀者可以直接閱讀幫助文檔進行學習。如果需要繼續查看某個命令的幫助信息,如build命令,則可以用go help build查看,如圖1.11所示。

圖1.11 go build幫助信息

從圖1.11可以看出,前面列出的go build參數實際上都是可以利用此命令查看得到的,其實官方的英文對參數的描述更加準確,因此建議多閱讀官方的幫助文檔來學習。

(4)vet命令是非常有用的一個工具。每個Go語言的開發者都應該了解并會使用這個內置的工具。vet命令會對Go源代碼進行靜態檢測分析,以發現可能的bug或者異常并進行提示,它是Go tool套件工具中go tool vet工具的封裝,和Go編譯器一起發布,不依賴任何第三方庫,因此可以很方便地調用。

可以用go vet hello.go對文件hello.go進行靜態分析,用go tool vet help或者go doc cmd/vet命令查看更多細節信息。vet工具可以對代碼進行如下檢測(包含但不限于):

· 檢查賦值語句。

· 檢查代碼中對代碼包sync/atomic的使用是否正確。

· 檢查編譯標簽的有效性。

· 檢查復合結構實例的初始化代碼。

· 檢查那些擁有標準命名的方法的簽名。

· 檢查代碼中對打印函數的使用是否正確。

· 檢查代碼中對在range語句塊中迭代賦值的變量的使用是否正確。

· 檢查結構類型的字段的標簽格式是否標準。

· 查找并報告不可到達的代碼。

利用這個工具,我們可以對code01目錄中的文件hello_vet.go進行靜態分析,以發現潛在的bug。在目錄code01中打開命令行,執行如下命令:

go vet hello_vet.go

則會輸出如下信息:

hello_vet.go:5:2: cannot find package "fmt1" in any of:
C:\Go\src\fmt1 (from $GOROOT)
C:\GoWork\src\fmt1 (from $GOPATH)

由此可見,vet工具提示在%GOROOT%和%GOPATH%目錄下沒有找到文件hello_vet.go內第5行語句需要導入的"fmt1"包,正確的包名應該是"fmt"。

注意

vet工具在檢測到潛在bug時會停止后續檢測,因此當修復某個bug后,需要用vet工具再次進行檢測。

主站蜘蛛池模板: 晋城| 尤溪县| 西盟| 金山区| 正镶白旗| 保山市| 河南省| 涞源县| 桐梓县| 左云县| 湖北省| 体育| 宜城市| 津市市| 乌鲁木齐县| 陇西县| 肥西县| 沂南县| 鄂伦春自治旗| 侯马市| 曲松县| 比如县| 江油市| 天等县| 安乡县| 无为县| 大邑县| 中西区| 昭通市| 河北区| 疏勒县| 临城县| 呼伦贝尔市| 潮州市| 龙南县| 万年县| 赤城县| 韶山市| 如东县| 璧山县| 南通市|