標籤:需要 類庫 user 提取 編譯器 包括 物件導向語言 標識 main
樣本 4.1 hello_world.go
package mainimport "fmt"func main() {fmt.Println("hello, world")}4.2.1 包的概念、匯入與可見度
包是結構化代碼的一種方式:每個程式都由包(通常簡稱為 pkg)的概念組成,可以使用自身的包或者從其它包中匯入內容。
如同其它一些程式設計語言中的類庫或命名空間的概念,每個 Go 檔案都屬於且僅屬於一個包。一個包可以由許多以 .go 為副檔名的源檔案組成,因此檔案名稱和包名一般來說都是不相同的。
你必須在源檔案中非注釋的第一行指明這個檔案屬於哪個包,如:package main。package main表示一個可獨立執行的程式,每個 Go 應用程式都包含一個名為 main 的包。
一個應用程式可以包含不同的包,而且即使你只使用 main 包也不必把所有的代碼都寫在一個巨大的檔案裡:你可以用一些較小的檔案,並且在每個檔案非注釋的第一行都使用 package main 來指明這些檔案都屬於 main 包。如果你打算編譯包名不是為 main 的源檔案,如 pack1,編譯後產生的對象檔案將會是 pack1.a 而不是可執行程式。另外要注意的是,所有的包名都應該使用小寫字母。
標準庫
在 Go 的安裝檔案裡包含了一些可以直接使用的包,即標準庫。在 Windows 下,標準庫的位置在 Go 根目錄下的子目錄 pkg\windows_386 中;在 Linux 下,標準庫在 Go 根目錄下的子目錄 pkg\linux_amd64 中(如果是安裝的是 32 位,則在 linux_386 目錄中)。一般情況下,標準包會存放在 $GOROOT/pkg/$GOOS_$GOARCH/ 目錄下。
Go 的標準庫包含了大量的包(如:fmt 和 os),但是你也可以建立自己的包(第 8 章)。
如果想要構建一個程式,則包和包內的檔案都必須以正確的順序進行編譯。包的依賴關係決定了其構建順序。
屬於同一個包的源檔案必須全部被一起編譯,一個包即是編譯時間的一個單元,因此根據慣例,每個目錄都只包含一個包。
如果對一個包變更或重新編譯,所有引用了這個包的用戶端程式都必須全部重新編譯。
Go 中的包模型採用了顯式依賴關係的機制來達到快速編譯的目的,編譯器會從尾碼名為 .o 的對象檔案(需要且只需要這個檔案)中提取傳遞依賴類型的資訊。
如果 A.go 依賴 B.go,而 B.go 又依賴 C.go:
- 編譯
C.go, B.go, 然後是 A.go.
- 為了編譯
A.go, 編譯器讀取的是 B.o 而不是 C.o.
這種機制對於編譯大型的項目時可以顯著地提升編譯速度。
如果包名不是以 . 或 / 開頭,如 "fmt" 或者 "container/list",則 Go 會在通用檔案進行尋找;如果包名以 ./ 開頭,則 Go 會在相對目錄中尋找;如果包名以 / 開頭(在 Windows 下也可以這樣使用),則會在系統的絕對路徑中尋找。
匯入包即等同於包含了這個包的所有的代碼對象。
除了符號 _,包中所有代碼對象的標識符必須是唯一的,以避免名稱衝突。但是相同的標識符可以在不同的包中使用,因為可以使用包名來區分它們。
包通過下面這個被編譯器強制執行的規則來決定是否將自身的代碼對象暴露給外部檔案:
可見度規則
當標識符(包括常量、變數、類型、函數名、結構欄位等等)以一個大寫字母開頭,如:Group1,那麼使用這種形式的標識符的對象就可以被外部包的代碼所使用(用戶端程式需要先匯入這個包),這被稱為匯出(像物件導向語言中的 public);標識符如果以小寫字母開頭,則對包外是不可見的,但是他們在整個包的內部是可見並且可用的(像物件導向語言中的 private )。
(大寫字母可以使用任何 Unicode 編碼的字元,比如希臘文,不僅僅是 ASCII 碼中的大寫字母)。
因此,在匯入一個外部包後,能夠且只能夠訪問該包中匯出的對象。
假設在包 pack1 中我們有一個變數或函數叫做 Thing(以 T 開頭,所以它能夠被匯出),那麼在當前包中匯入 pack1 包,Thing 就可以像物件導向語言那樣使用點標記來調用:pack1.Thing(pack1 在這裡是不可以省略的)。
因此包也可以作為命名空間使用,協助避免命名衝突(名稱衝突):兩個包中的同名變數的區別在於他們的包名,例如 pack1.Thing 和 pack2.Thing。
你可以通過使用包的別名來解決包名之間的名稱衝突,或者說根據你的個人喜好對包名進行重新設定,如:import fm "fmt"。下面的代碼展示了如何使用包的別名:
樣本 4.2 alias.go
package mainimport fm "fmt" // alias3func main() { fm.Println("hello, world")}
注意事項
如果你匯入了一個包卻沒有使用它,則會在構建程式時引發錯誤,如 imported and not used: os,這正是遵循了 Go 的格言:“沒有不必要的代碼!“。
摘自:https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/04.2.md
go語言筆記——包的概念本質上和java是一樣的,通過大小寫來區分private