在過去的幾年裡,我與廣大愛好者一起見證了 Go 語言的崛起。
從 Go 1.5 版本的自舉(即用 Go 語言編寫程式來實作 Go 語言自身),到 Go 1.7 版本的極速 GC(也稱垃圾回收器),再到 2018 年 2 月釋出的 Go 1.10 版本對其自帶工具的全面更新,以及可預見的後續版本關鍵特性(比如用來做程式依賴管理的
go mod
指令),這一切都令我們歡欣鼓舞。Go 語言在一步步走向輝煌的同時,顯然已經成為軟體工程師們最喜愛的程式設計語言之一。
我開辦這個專欄的主要目的,是要與你一起探索 Go 語言的奧秘,并幫助你在學習和實踐的過程中擷取更多。
我假設本專欄的讀者已經具備了一定的計算機基礎,比如,你要知道作業系統是什麼、環境變量怎麼設定、怎樣正确使用指令行,等等。
當然了,如果你已經有了程式設計經驗,尤其是一點點 Go 語言程式設計經驗,那就更好了,畢竟我想教給你的,都是 Go 語言中非常核心的技術。
如果你對 Go 語言中最基本的概念和文法還不夠了解,那麼可能需要在學習本專欄的過程中去查閱Go 語言規範文檔,也可以把預習篇的基礎知識圖拿出來好好研究一下。
最後,我來說一下專欄的講述模式。我總會以一道 Go 語言的面試題開始,針對它進行解答,我會告訴你為什麼我要關注這道題,這道題的背後隐藏着哪些知識,并且,我會對這部分的内容,進行相關的知識擴充。
好了,準備就緒,我們一起開始。
我們學習 Go 語言時,要做的第一件事,都是根據自己電腦的計算架構(比如,是 32 位的計算機還是 64 位的計算機)以及作業系統(比如,是 Windows 還是 Linux),從Go 語言官網下載下傳對應的二進制包,也就是可以拿來即用的安裝包。
随後,我們會解壓縮安裝包、放置到某個目錄、配置環境變量,并通過在指令行中輸入
go version
來驗證是否安裝成功。
在這個過程中,我們還需要配置 3 個環境變量,也就是 GOROOT、GOPATH 和 GOBIN。這裡我可以簡單介紹一下。
- GOROOT:Go 語言安裝根目錄的路徑,也就是 GO 語言的安裝路徑。
- GOPATH:若幹工作區目錄的路徑。是我們自己定義的工作空間。
- GOBIN:GO 程式生成的可執行檔案(executable file)的路徑。
其中,GOPATH 背後的概念是最多的,也是最重要的。那麼,今天我們的面試問題是:你知道設定 GOPATH 有什麼意義嗎?
關于這個問題,它的典型回答是這樣的:
你可以把 GOPATH 簡單了解成 Go 語言的工作目錄,它的值是一個目錄的路徑,也可以是多個目錄路徑,每個目錄都代表 Go 語言的一個工作區(workspace)。
我們需要利于這些工作區,去放置 Go 語言的源碼檔案(source file),以及安裝(install)後的歸檔檔案(archive file,也就是以“.a”為擴充名的檔案)和可執行檔案(executable file)。
事實上,由于 Go 語言項目在其生命周期内的所有操作(編碼、依賴管理、建構、測試、安裝等)基本上都是圍繞着 GOPATH 和工作區進行的。是以,它的背後至少有 3 個知識點,分别是:
1. Go 語言源碼的組織方式是怎樣的;
2. 你是否了解源碼安裝後的結果(隻有在安裝後,Go 語言源碼才能被我們或其他代碼使用);
3. 你是否了解建構和安裝 Go 程式的過程(這在開發程式以及查找程式問題的時候都很有用,否則你很可能會走彎路)。
下面我就重點來聊一聊這些内容。
知識擴充
1. Go 語言源碼的組織方式
與許多程式設計語言一樣,Go 語言的源碼也是以代碼包為基本組織機關的。在檔案系統中,這些代碼包其實是與目錄一一對應的。由于目錄可以有子目錄,是以代碼包也可以有子包。
一個代碼包中可以包含任意個以.go 為擴充名的源碼檔案,這些源碼檔案都需要被聲明屬于同一個代碼包。
代碼包的名稱一般會與源碼檔案所在的目錄同名。如果不同名,那麼在建構、安裝的過程中會以代碼包名稱為準。
每個代碼包都會有導入路徑。代碼包的導入路徑是其他代碼在使用該包中的程式實體時,需要引入的路徑。在實際使用程式實體之前,我們必須先導入其所在的代碼包。具體的方式就是
import
該代碼包的導入路徑。就像這樣:
import "github.com/labstack/echo"
在工作區中,一個代碼包的導入路徑實際上就是從 src 子目錄,到該包的實際存儲位置的相對路徑。
是以說,Go 語言源碼的組織方式就是以環境變量 GOPATH、工作區、src 目錄和代碼包為主線的。一般情況下,Go 語言的源碼檔案都需要被存放在環境變量 GOPATH 包含的某個工作區(目錄)中的 src 目錄下的某個代碼包(目錄)中。
2. 了解源碼安裝後的結果
了解了 Go 語言源碼的組織方式後,我們很有必要知道 Go 語言源碼在安裝後會産生怎樣的結果。
源碼檔案以及安裝後的結果檔案都會放到哪裡呢?我們都知道,源碼檔案通常會被放在某個工作區的 src 子目錄下。
那麼在安裝後如果産生了歸檔檔案(以“.a”為擴充名的檔案),就會放進該工作區的 pkg 子目錄;如果産生了可執行檔案,就可能會放進該工作區的 bin 子目錄。
我再講一下歸檔檔案存放的具體位置和規則。
源碼檔案會以代碼包的形式組織起來,一個代碼包其實就對應一個目錄。安裝某個代碼包而産生的歸檔檔案是與這個代碼包同名的。
放置它的相對目錄就是該代碼包的導入路徑的直接父級。比如,一個已存在的代碼包的導入路徑是
github.com/labstack/echo,
那麼執行指令
go install github.com/labstack/echo
生成的歸檔檔案的相對目錄就是 github.com/labstack, 檔案名為 echo.a。
順便說一下,上面這個代碼包導入路徑還有另外一層含義,那就是:該代碼包的源碼檔案存在于 GitHub 網站的 labstack 組的代碼倉庫 echo 中。
再說回來,歸檔檔案的相對目錄與 pkg 目錄之間還有一級目錄,叫做平台相關目錄。平台相關目錄的名稱是由 build(也稱“建構”)的目标作業系統、下劃線和目标計算架構的代号組成的。
比如,建構某個代碼包時的目标作業系統是 Linux,目标計算架構是 64 位的,那麼對應的平台相關目錄就是 linux_amd64。
是以,上述代碼包的歸檔檔案就會被放置在目前工作區的子目錄 pkg/linux_amd64/github.com/labstack 中。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5CNykzMyYWY2UDMlRjY1YDNzYzX4MDNxQTMyEzLcBTMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
(GOPATH 與工作區)
總之,你需要記住的是,某個工作區的 src 子目錄下的源碼檔案在安裝後一般會被放置到目前工作區的 pkg 子目錄下對應的目錄中,或者被直接放置到該工作區的 bin 子目錄中。
3. 了解建構和安裝 Go 程式的過程
我們再來說說建構和安裝 Go 程式的過程都是怎樣的,以及它們的異同點。
建構使用指令
go build
,安裝使用指令
go install
。建構和安裝代碼包的時候都會執行編譯、打包等操作,并且,這些操作生成的任何檔案都會先被儲存到某個臨時的目錄中。
如果建構的是庫源碼檔案,那麼操作的結果檔案隻會存在于臨時目錄中。這裡的建構的主要意義在于檢查和驗證。
如果建構的是指令源碼檔案,那麼操作的結果檔案會被搬運到源碼檔案所在的目錄中。
安裝操作會先執行建構,然後還會進行連結操作,并且把結果檔案搬運到指定目錄。進一步說,如果安裝的是庫源碼檔案,那麼結果檔案會被搬運到它所在工作區的 pkg 目錄下的某個子目錄中。
如果安裝的是指令源碼檔案,那麼結果檔案會被搬運到它所在工作區的 bin 目錄中,或者環境變量
GOBIN
指向的目錄中。
這裡你需要記住的是,建構和安裝的不同之處,以及執行相應指令後得到的結果檔案都會出現在哪裡。