這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
1.Go語言環境搭建及基礎知識
Go語言官方網站(http://golang.org)
程式碼封裝文檔網站(http://godoc.org)
Go語言中文網(http://studygolang.com)
Go語言開發包下載路徑:
go1.6.2.linux-amd64(包含part1和part2兩部分,下載後一起解壓)
http://download.csdn.net/download/u012855229/9560392
http://download.csdn.net/download/u012855229/9560394
go1.6.2.windows-amd64(包含part1和part2兩部分,下載後一起解壓)
http://download.csdn.net/download/u012855229/9560395
http://download.csdn.net/download/u012855229/9560400
《Go並發編程實戰》完整PDF下載路徑:(包含part1和part2兩部分,下載後一起解壓)
http://download.csdn.net/download/u012855229/9560311
http://download.csdn.net/download/u012855229/9560304
《Go並發編程實戰》所用到的源碼執行個體下載路徑:
https://github.com/hyper-carrot/goc2p
1.1 go語言配置環境變數
-
windows下:
-
GOROOT={你的Go語言的根目錄}
在環境變數PATH後追加;%GOROOT%\bin
-
linux下:
-
Go語言官方建議把go檔案夾複製到/usr/local目錄中,但也可以複製到其他目錄;編輯/etc/profile檔案,如下:
export GOROOT=/usr/local/go
export PATH=$PATH:$GOROOT/bin
儲存/etc/profile檔案,使用source /etc/profile使配置生效。
(具體linux配置環境變數可以Google,Baidu,這裡不贅述了)
注意: 路徑串連符windows下是”\”,linux下是 “/”
-
Go語言還有兩個隱含的環境變數—-GOOS和GORACH
-
GOOS代表程式構建環境的目標作業系統,其值可以是liunx,windows,freebsd,darwin;
GORACH代表程式構建環境的目標計算架構,其值可以是386,amd64或arm;
之後提到的
平台相關目錄是通過${GOOS}_${GORACH}的方式來命名的。
(如Go歸檔檔案的存放路徑就是根據“平台相關目錄”來指定的)
設定好環境變數後,在命令列中輸入go出現如下資訊,表示成功。
Go is a tool for managing Go source code.
Usage:
go command [arguments]
The commands are:
build compile packages and dependencies clean remove object files doc show documentation for package or symbol env print Go environment information fix run go tool fix on packages fmt run gofmt on package sources generate generate Go files by processing source get download and install packages and dependencies install compile and install packages and dependencies list list packages run compile and run Go program test test packages tool run specified go tool version print Go version vet run go tool vet on packages
Use “go help [command]” for more information about a command.
Additional help topics:
c calling between Go and C buildmode description of build modes filetype file types gopath GOPATH environment variable environment environment variables importpath import path syntax packages description of package lists testflag description of testing flags testfunc description of testing functions
Use “go help [topic]” for more information about that topic.
1.2 工作區
Go代碼必須放在工作區中,工作區其實就是一個對應於特定工程的目錄,它包含3個子目錄src目錄,pkg目錄和bin目錄。
-
src目錄
-
用於以程式碼封裝的形式組織並儲存Go源碼檔案。這裡的程式碼封裝,與src下的子目錄一一對應。例如,若一個源碼檔案被聲明為屬於程式碼封裝logging,那麼它就應當被儲存在src目錄下名為logging的子目錄中。當然,我們也可以把Go源碼檔案直接放於src目錄下,但這樣的Go源碼檔案就只能被聲明為屬於main程式碼封裝了。除非用於臨時測試或示範,一般還是建議把Go源碼檔案放入特定的程式碼封裝中。
-
pkg目錄
-
用於存放經由go install命令構建安裝後的程式碼封裝(包含Go庫源碼檔案)的”*.a”歸檔檔案。該目錄與GOROOT目錄下的pkg功能類似,區別在於,工作區中的pkg目錄專門用來存放使用者代碼的歸檔檔案。構建和安裝使用者源碼的過程一般會以程式碼封裝為單位進行,比如logging包被編譯安裝後,將產生一個名為logging.a的歸檔檔案,並存放在當前工作區的pkg目錄下的平台相關目錄中。
-
bin目錄
-
與pkg目錄類似,在通過go install命令完成安裝後,儲存由Go命令源碼檔案產生的可執行檔。在Linux作業系統下,這個可執行檔一般是一個與源碼檔案同名的檔案。在Windows作業系統下,這個可執行檔的名稱是源碼檔案名稱加.exe尾碼。
1.3 GOPATH
工作區的目錄路徑需要添加到環境變數GOPATH中。否則,即使處於同一個工作區(事實上,未被加入到環境變數GOPATH中的目錄不應該稱作工作區),代碼之間也無法通過絕對程式碼封裝路徑完成調用。在實際開發中,工作區往往有多個,這些工作區的目錄路徑都需要添加至GOPATH中。
如Linux下有兩個工作區:
~/Go/lib
~/Go/goc2p
修改/etc/profile檔案,添加環境變數GOPATH的內容:
export GOPATH=$HOME/Go/lib:$HOME/Go/goc2p
儲存/etc/profile檔案,並用source命令使配置生效。
注意:
- GOPATH中不要包含環境變數GOROOT的值(即Go的安裝目錄路徑),將Go語言本身的工作區和使用者的工作區嚴格地分開;
- 通過Go工具中的代碼擷取命令go get,可以將指定項目的源碼下載到我們在環境變數GOPATH中設定的第一個工作區中,並在其中完成構建和安裝的過程。
Windows下直接在系統變數中添加GOPATH環境變數即可,其中值為你的工作區的根目錄。
1.4 源碼檔案
Go語言的源碼檔案分為3類:Go庫源碼檔案,Go命令源碼檔案和Go測試源碼檔案。
命令源碼檔案
聲明為屬於main程式碼封裝,並且包含無參數聲明和結果聲明的main函數的源碼檔案。這類檔案可以獨立運行(使用go run命令),也可以被go build或go install命令轉換為可執行檔。
同一個程式碼封裝中的所有源碼檔案,其所屬程式碼封裝的名稱必須一致。如果命令源碼檔案和庫源碼檔案處於同一程式碼封裝中,該包就無法正確執行go build和go install命令。換句話說,這些源碼檔案也就無法被編譯和安裝。因此,命令源碼檔案通常會單獨放在一個程式碼封裝中。一般情況下,一個程式模組或軟體的啟動入口只有一個。
同一個程式碼封裝中可以有多個命令源碼檔案,可通過go run命令分別運行它們。但通過go build和go install命令無法編譯和安裝該程式碼封裝。所以一般情況下,不建議把多個命令源碼檔案放在同一個程式碼封裝中。
當程式碼封裝中有且僅有一個命令源碼檔案時,在檔案所在目錄中執行go build命令,即可在該目錄下產生一個與目錄同名的可執行檔;若使用go install命令,則可在當前工作區的bin目錄下產生相應的可執行檔。
庫源碼檔案
存在於某個程式碼封裝中的普通源碼檔案。通常,庫源碼檔案聲明的包名會與它實際所屬的程式碼封裝(目錄)名一致,且庫源碼檔案中不包含無參數聲明和無結果聲明的main函數。如在basic/set目錄下執行go install命令,成功地安裝了basic/set包,並產生一個名為set.a的歸檔檔案。歸檔檔案的存放目錄由以下規則產生:
- 安裝庫源碼檔案時所產生的歸檔檔案會被存放到當前工作區的pkg目錄中。
- 根據被編譯的目標電腦架構,歸檔檔案會被放置在pkg目錄下的平台相關目錄中。如上的set.a在我的64位window系統上就是pkg\windows_amd64目錄中。
- 存放歸檔檔案的目錄的相對路徑與被安裝的程式碼封裝的上一級程式碼封裝的相對路徑是一致的。第一個相對路徑就是相對於工作區的pkg目錄下的平台相關目錄而言的,而第二個相對路徑是相對於工作區的src目錄而言的。如果被安裝的程式碼封裝沒有上一級程式碼封裝(也就是說它的父目錄就是工作的src目錄),那麼它的歸檔檔案就會被直接存放到當前工作區的pkg目錄的平台相關目錄下。如basic包的歸檔檔案basic.a總會被直接存放到pkg\windows_amd64目錄下,而basic/set包的歸檔檔案set.a則會被存放到pkg\ windows_amd64\basic目錄下。
測試源碼檔案
這是一種特殊的庫檔案,可以通過執行go test命令運行當前程式碼封裝下的所有測試源碼檔案。成為測試源碼檔案的充分條件有兩個:
- 檔案名稱需要以”_test.go”結尾
- 檔案中需要至少包含該一個名稱為”Test”開頭或”Benchmark”開頭,擁有一個類型為”testing.T”或”testing.B”的參數的函數。類型”testing.T”或”testing.B”分別對應功能測試和基礎測試所需的結構體。
當在某個程式碼封裝中執行go test命令,該程式碼封裝中的所有測試源碼檔案就會被找到並運行。
注意:儲存Go代碼的文字檔需要以UTF-8編碼儲存。如果源碼檔案中出現了非UTF-8編碼的字元,則在運行、編譯或安裝時,Go會拋出“illegal UTF-8 sequence”的錯誤。
1.5 程式碼封裝
Go語言中的程式碼封裝是對代碼進行構建和打包的基本單元。
包聲明
在Go語言中,程式碼封裝中的源碼檔案名稱可以是任意的;這些任意名稱的源碼檔案都必須以包聲明語句作為檔案中代碼的第一行。比如src目錄下的程式碼封裝basic/set包中的所有源碼檔案都要先聲明自己屬於basic/set包:
package set
package是Go語言中用於包聲明語句的關鍵字。Go語言規定包聲明中的包名為程式碼封裝路徑的最後一個元素。如上,basic/set包的包路徑為basic/set,而包聲明中的包名則為set。除了命令源碼檔案不論存放在哪個包中,都必須聲明為屬於main包。
包匯入
程式碼封裝的匯入使用程式碼封裝匯入路徑。程式碼封裝匯入路徑就是程式碼封裝在工作區的src目錄下的相對路徑,比如basic的絕對路徑為E:\Go\goc2p\src\basic\set,而E:\Go\goc2p是被包含在環境變數GOPATH中的工作區目錄路徑,則其程式碼封裝匯入路徑就是basic/set。
import basic/set
當匯入多個程式碼封裝時,需要用圓括弧括起它們,且每個程式碼封裝名獨佔一行。在調用被匯入程式碼封裝中的函數或使用其中的結構體、變數或常量時,需要使用包路徑的最後一個元素加”.”的方式指定代碼所在的包。
如果我們有兩個包logging和go_lib/logging,並且有相同的方法NewSimpleLogger(),且有一個源碼檔案需要匯入這兩個包:
import ( "logging" "go_lib/logging" )
則這句代碼logging.NewSimpleLogger()就會引起衝突,Go語言無法知道logging. 代表的是哪一個包。所以,在Go語言中,如果在同一個源碼檔案中匯入多個程式碼封裝,那麼程式碼封裝路徑的最後一個元素不可以重複。
如果用這段程式碼封裝匯入代碼,在編譯代碼時,Go語言會拋出”logging redeclared as imported package name”的錯誤。如果確實需要匯入,當有這類重複時,我們可以給它們起個別名來區別:
import ( la "logging" lb "go_lib/logging" )
調用包中的代碼:
var logger la.Logger = la.NewSimpleLogger()
這裡不必給每個引起衝突的程式碼封裝都起一個別名,只要能夠區分它們就可以了。
如果我們想直接調用某個依賴包的程式,就可以用”.”來代替別名。
import ( . "logging" lb "go_lib/logging" )
在當前源碼檔案中,可以直接進行代碼調用了:
var logger Logger = NewSimpleLogger()
Go語言把變數、常量、函數、結構體和介面統稱為程式實體,而把它們的名字統稱為標識符。標識符可以是任何Unicode編碼可以表示的字母字元、數字以及底線”_”,並且,首字母不能是數字或底線。
標識符的首字母的大小寫控制著對應程式實體的存取權限。如果標識符的首字母是大寫的,那麼它對應的程式實體就可以被本程式碼封裝之外的代碼訪問到,也可以稱其為可匯出的。否則對應的程式實體就只能被本包內的代碼訪問。當然,還需要有以下兩個額外條件:
- 程式實體必須是非局部的。局部程式實體是被定義在函數或結構體的內部。
- 程式碼封裝所在的目錄必須被包含在環境變數GOPATH中的工作區目錄中。
如果程式碼封裝logging中有一個叫做getSimpleLogger的函數,那麼光從這個函數的名字上我們就可以看出,這個函數是不能被包外代碼調用的。
如果我們只想初始化某個程式碼封裝而不需要再當前源碼檔案中使用那個程式碼封裝中的任何代碼,既可以用”_”來代替別名
import ( _ “logging” )
包初始化
在Go語言中,可以有專門的函數負責程式碼封裝初始化。這個函數需要無參數聲明和結果聲明,且名稱必須為init,如下:
func init() { println("Initialize") }
Go語言會在程式真正執行前對整個程式的依賴進行分析,並初始化相關的程式碼封裝。也就是說,所有的程式碼封裝初始化函數都會在main函數(命令源碼檔案中的入口函數)之前執行完成,而且只會執行一次。並且,當前程式碼封裝中的所有全域變數的初始化都會在程式碼封裝初始化函數執行前完成。這就避免了在程式碼封裝初始化函數對某個變數進行賦值之後又被該變數聲明中賦予的值覆蓋掉的問題。
這裡舉出《Go並發編程實戰》中的例子,協助理解上面的包初始化,如下:
package main // 命令源碼檔案必須在這裡聲明自己屬於main包 import ( // 引入了程式碼封裝fmt和runtime "fmt" "runtime" ) func init() { // 包初始化函數 fmt.Printf("Map: %v\n", m) // 先格式化再列印 // 通過調用runtime包的代碼擷取當前機器所啟動並執行作業系統以及計算架構 // 而後通過fmt包的Sprintf方法進行字串格式化並賦值給變數info info = fmt.Sprintf("OS: %s, Arch: %s", runtime.GOOS, runtime.GOARCH) } // 非局部變數,map類型,且已初始化 var m map[int]string = map[int]string{1: "A", 2: "B", 3: "C"} var info string // 非局部變數,string類型,未被初始化 func main() { // 命令源碼檔案必須有的入口函數 fmt.Println(info) // 列印變數info }
命名源碼檔案名稱為initpkg_demo.go,並儲存到工作區的basic/pkginit包中。如為我本機啟動並執行結果:
在同一個程式碼封裝中,可以存在多個程式碼封裝初始化函數,甚至程式碼封裝內的每一個源碼檔案都可以定義多個程式碼封裝初始化函數。Go語言編譯器不能保證同一個程式碼封裝中的多個程式碼封裝初始化函數的執行順序。如果要求按特定順序執行的話,可以考慮使用Channel(Go語言並發編程模型的一員)進行控制。
Go語言認可兩個特殊的程式碼封裝名稱—-all 和 std. all代表了環境變數GOPATH中包含的所有工作區中的所有程式碼封裝,而std則代表了Go語言標準庫中的所有程式碼封裝。
標準命令概述
- build 編譯給定的程式碼封裝或Go語言源碼檔案及其依賴包
- clean 清除執行其他go命令後遺留的目錄和檔案
- doc 執行godoc命令以列印指定程式碼封裝。
- env 列印Go語言環境資訊
- fix 執行go tool fix命令以修正給定程式碼封裝的源碼檔案中包含的過時文法和代碼調用
- fmt 執行gofmt命令以格式化戈丁程式碼封裝中的源碼檔案。
- generate generate Go files by processing source
- get 下載和安裝給定的程式碼封裝及其依賴包
- install 編譯和安裝給定的程式碼封裝及其依賴包
- list 顯示給定程式碼封裝的資訊
- run 編譯並運行給定的命令源碼檔案
- test 測試給定的程式碼封裝
- tool 運行Go語言的特殊工具
- version 顯示當前安裝的Go語言的版本資訊
- vet run go tool vet on packages
在執行上述命令的時候可以通過附加一些額外的標記來定製命令的執行過程,這些標記可以看做是命令的特殊參數,這些特殊參數可以添加到命令名稱和命令的真正參數中間,如下:
- -a 強行重新構建所有涉及的Go語言程式碼封裝(包括Go語言標準庫中的程式碼封裝),即使它們已經是最新的了。
- -n 使命令僅列印在執行期間使用到的所有命令,而不真正執行它們。
- -v 列印出命令執行過程中涉及的Go語言程式碼封裝的名字。這些程式碼封裝一般包括我們自己給定的目標程式碼封裝,有時候還會包括該程式碼封裝直接或間接依賴的程式碼封裝。
- -work 列印出命令執行時產生和使用的臨時工作目錄的名字,且命令執行完成後不對它進行刪除。
- -x 列印出命令執行期間使用到的所有命令。
常用的Go語言的特殊工具,如下:
- fix 可以把給定程式碼封裝的所有Go語言源碼檔案中的舊版本代碼修改為新版本。它是我們升級Go語言版本後會使用到的工具。
- vet 用於檢查Go語言源碼中靜態錯誤的簡單工具。可以使用它檢測一些常見的Go語言代碼編寫錯誤。
- pprof 用於以互動的方式訪問一些效能概要檔案。命令將會分析給定的概要檔案,並根據要求提供高可讀性的輸出資訊。這個工具可以分析的概要檔案包括CPU概要檔案、記憶體概要檔案和程式阻塞概要檔案。這些內含Go語言運行時資訊的概要檔案可以通過標準庫程式碼封裝runtime和runtime/pprof中的程式來產生。
- cgo 用於協助Go語言代碼使用C語言程式碼程式庫,以及使用Go語言代碼可以被C語言代碼引用。
最後附上《Go並發編程實戰》作者郝林託管到GitHub的Go命令教程,裡面涉及了Go命令和工具的詳細用法:
https://github.com/hyper-carrot/go_command_tutorial
Go語言學習的第一天,以後持續更新。。。