包(package) 用于組織 Go 源代碼,提供了更好的可重用性與可讀性。Go 語言有超過 100 個的标準包,可以用
go list std | wc -l
指令檢視标準包的具體數目,标準庫為大多數的程式提供了必要的基礎元件。
10.1 main 包
首先,我們先來看看
main
包,該包中包含一個
main()
函數,該函數是程式運作的入口。
package packagename
代碼指定了某一源檔案屬于某一個包。它應該放在每一個源檔案的第一行。例如我們 Go 的第一個程式。
// hello go
package main
import "fmt"
func main() {
fmt.Println("《Go語言極簡一本通》")
}
package main
這一行指定該檔案屬于
main
包。
import "fmt"
語句用于導入一個已存在的名為
fmt
的包。
10.2 建立包
下面我們建立自定義的
book
包,其中,屬于某一個包的源檔案都應該放置于一個單獨命名的檔案夾裡,按照 Go 的慣例,應該用包名命名該檔案夾。是以應當先建立一個
book
檔案夾,位于該目錄下建立一個
book.go
源檔案,裡面實作我們自定義的數學加法函數。請注意函數名的首字母要大寫。
// book.go
package book
func ShowBookInfo(bookName, authorName string) (string, error) {
if bookName == "" {
return "", errors.New("圖書名稱為空")
}
if authorName == "" {
return "", errors.New("作者名稱為空")
}
return bookName + ",作者:" + authorName, nil
}
Tips:
- 導出名字(Exported Names)
- 我們将
包中的函數book
首字母大寫。在 Go 中這具有特殊意義。在 Go 中,任何以大寫字母開頭的變量或者函數都是被導出的名字。其它包隻能通路被導出的函數和變量。在這裡,我們需要在ShowBookInfo
包中通路main
函數,是以會将它們的首字母大寫。ShowBookInfo
- 如果在
中将函數名從book.go
變為ShowBookInfo
,并且在showBookInfo
中調用main.go
函數,則該程式編譯不通過。因為如果想在包外通路一個函數,它應該首字母大寫。book.showBookInfo
- 我們将
10.3 導入包
使用包之前我們需要導入包,在 GoLand 中會幫你自動導入所需要的包。導入包的文法為
import path
,其中
path
可以是相對于工作區檔案夾的相對路徑,也可以是絕對路徑。
package main
import (
"fmt"
"book"
)
func main() {
bookName := "《Go語言極簡一本通》"
author := "歡喜"
bookInfo, _ := book.ShowBookInfo(bookName, author)
fmt.Println("bookInfo = ", bookInfo)
}
導入包可以單行導入也可以多行導入,像上面的程式代碼就是多行導入的例子,一般我們也建議使用多行導入,當然你也可以使用單行導入:
import "fmt"
import "book"
10.4 使用别名
如果我們導入了兩個具有同一包名的包時會産生沖突,這時我們可以為其中一個包定義别名:
import (
"crypto/rand"
mrand "math/rand" // 将名稱替換為 mrand 避免沖突
)
當然,我們也可以使用别名代替名字很長的包名。
10.5 使用點操作
導入一個包後,如果要使用該包中的函數,都要使用
包名.方法名
文法進行調用,對于一些使用高頻的包,例如
fmt
包,每次調用列印函數時都要使用
fmt.Println()
進行調用,很不友善。我們可以在導入包的時,使用
import . package_path
文法。從此,我們列印再也不用加
fmt
了。
import . "fmt"
func main() {
Println("hello, world")
}
但這種用法,會有一定的隐患,就是導入的包裡可能有函數,會和我們自己的函數發生沖突。
10.6 包的初始化
每個包都允許有一個或多個
init
函數,
init
函數不應該有任何傳回值類型和參數,在代碼中也不能顯式調用它,當這個包被導入時,就會執行這個包的
init
函數,做初始化任務,
init
函數優先于
main
函數執行。該函數形式如下:
func init() {
}
包的初始化順序:首先初始化 包級别(Package Level) 的變量,緊接着調用
init
函數。包可以有多個
init
函數(在一個檔案或分布于多個檔案中),它們按照編譯器解析它們的順序進行調用。如果一個包導入了另一個包,會先初始化被導入的包。盡管一個包可能會被導入多次,但是它隻會被初始化一次。
10.7 包的匿名導入
import _ "fmt"