Go包-程式碼組織者
前言
在上一節(聊聊Go的工作空間),提到了Go包,這一節,我們就來仔細講講。
什麼是Go包
Go語言中的包,其實是一種組織程式碼的方式。Go 的程式都會組織成若干組檔案,而每組檔案被稱為一個包。go安裝完成之後,在GOROOT/src
目錄,自帶了各種各樣的包,例如常用的io
包、fmt
包、math
包等。我們就來分析下io
包,看看go內建的包是如何組織程式碼的。
上圖顯示的就是io
包的目錄結構,分別開啟io.go
、multi.go
和pipe.go
,你會發現在檔案非註釋的第一行都聲明瞭package io
。沒錯,這三個原始檔都屬於同一個go包–io
包。到這裡,其實已經很明白了,所謂的go包就是計算機中的目錄,通俗點講就是檔名。go語言就是這樣通過它們進行目錄結構和檔案組織的。在io
ioutil
包,感興趣的同學可以開啟ioutil
目錄下的檔案,一探究竟。(以_test.go
結尾的測試檔案,忽略)
包應該如何命名
使用關鍵字–package
。和go檔案所在目錄同名,這是go包命名的最大原則,其次還應該做到簡潔、清晰且全小寫。這種命名方式有利於開發時書寫包名,查詢和定位。例如,上面提到的 io
包、ioutil
包,命名都很簡短且清晰。所屬io
包的三個檔案,在檔案開頭都聲明瞭package io
。
包的匯入
使用關鍵字–import
。使用一個包,必須先將包匯入(不管是go內建包還是自己寫的包)。例如:
// 匯入單個包
import "fmt"
// 使用go語言提供的匯入快,匯入多個包,每個包獨佔一行
import (
"fmt"
"io/ioutil"
"github.com/Seekload/stringutil"
)
import
告訴編譯器到磁碟的哪裡去找想要匯入的包。其實,上面匯入fmt
、io/ioutil
和github.com/Seekload/stringutil
是一個相對路徑,編譯器會使用 Go 環境變數(GOROOT
和GOPATH
)設定的路徑,通過引入的相對路徑來查詢磁碟上的包。例如io/ioutil
,編譯器最終會在GOROOT/src/io/ioutil
路徑下查詢到ioutil
包。類似的,會在GOPATH/src/github.com/Seekload/stringutil
stringutil
包。提一點:編譯器在查詢的時候,會優先在GOROOT
路徑下查詢,其次,在GOPATH
下查詢,查詢無果之後會報編譯錯誤。匯入包完成之後,就可以使用包提供的常量、函式等,例如:
fmt.Println();
ioutil.ReadDir();
獲取遠端包
某一天,你在瀏覽github
,發現一個函式豐富的包,想在自己的專案上使用,目前,你想到的引用辦法可能就是直接將包clone
到本地,然後放到GOPATH/src/
目錄,開始引用。其實,有一種更簡便的方式,就是遠端匯入–使用go get
命令。這種匯入的前提就是,包託管在一個分散式的版本控制系統上,比如Github等,並且是Public的許可權。
我在GitHub上就有一個github.com/Seekload/stringutil
包(使用自己的域名作為包名一部分是為了避免包名重複,GitHub上的包太多了~),大家可以跟著我實操一下:
大家看下,我的工作空間目前是這樣的,
在GOPATH
執行go get github.com/Seekload/stringutil
匯入遠端包之後:
可以看到stringutil
包已經下載到工作空間,並且已經生成靜態庫檔案stringutil.a
,說明對包已進行過編譯和安裝。注意:go get
工具可以遞迴獲取依賴包,如果github.com/Seekload/stringutil
也引用了其他的遠端包,也可以一併下載下來。
好了,現在就可以在hello.go
中匯入包了
package main
import (
"fmt"
"github.com/Seekload/stringutil"
)
func main() {
fmt.Println(stringutil.Reverse("!oG ,daolkeeS"))
}
執行編譯安裝go install hello/
,生成可執行檔案hello
命名匯入
import
支援多個包匯入,如果匯入的包出現重名,該怎麼辦?別擔心,Go開發團隊已經考慮到這個問題了,提供給我們的方法就是,對匯入的包重新命名–即命名匯入:在 import
語句給出的包路徑的左側定義一個名字,將匯入的包命名為新名字。看程式碼:
package main
import (
"fmt"
myfmt "github.com/Seekload/stringutil/fmt"
)
func main() {
fmt.Println()
myfmt.Println()
}
如果,程式碼裡匯入了一個沒有用到的包,Go編譯器不會告警,而是直接編譯失敗,並丟擲一個錯誤。Go 開發團隊認為,匯入的包應該被使用。不然,無用的包過多,會使程式碼變得臃腫且管理繁瑣。不過,有時,我們需要匯入一個包,但是又用不到,怎麼辦?沒關係,Go提供了空白識別符號 _
來重新命名這個包匯入。
package main
import (
"fmt"
_ "github.com/Seekload/stringutil/fmt"
)
這裡提到了下劃線字元_
,以後還會接觸到。
下劃線字元
_
稱為空白識別符號,作用:拋棄不想繼續使用的值,如給匯入的包賦予一個空名字,或者忽略函式返回的你不感興趣的值。
關於Go包就講解到這裡,歡迎大家掃碼關注公眾號,敬請期待更多精彩文章!