任何源代碼文件必須屬于某個包,同時源碼文件的第一行有效代碼必須是package pacakgeName 語句,通過該語句聲明自己所在的包。
包可以定義在很深的目錄中,包名的定義是不包括目錄路徑的,但是包在引用時一般使用全路徑引用。比如在GOPATH/src/a/b/ 下定義一個包 c。在包 c 的源碼中只需聲明為package c,而不是聲明為package a/b/c,但是在導入 c 包時,需要帶上路徑,例如import "a/b/c"。
包名為 main 的包為應用程序的入口包,編譯不包含 main 包的源碼文件時不會得到可執行文件。
## 導入
要在代碼中引用其他包的內容,需要使用 import 關鍵字導入使用的包。
```
import "包的路徑"
```
- import 導入語句通常放在源碼文件開頭包聲明語句的下面;
- 導入的包名需要使用雙引號包裹起來;
- 包名是從GOPATH/src/ 后開始計算的,使用/ 進行路徑分隔。
**單行導入**
```
import "包 1 的路徑"
import "包 2 的路徑"
```
**多行導入**
```
import (
"包 1 的路徑"
"包 2 的路徑"
)
```
包的引用路徑有兩種寫法,分別是全路徑導入和相對路徑導入。
**全路徑導入**
包的絕對路徑就是GOROOT/src/或GOPATH/src/后面包的存放路徑
**相對路徑導入**
相對路徑只能用于導入GOPATH 下的包,標準包的導入只能使用全路徑導入。
例如包 a 的所在路徑是GOPATH/src/lab/a,包 b 的所在路徑為GOPATH/src/lab/b,如果在包 b 中導入包 a ,則可以使用相對路徑導入方式
```
import "../a"
```
## 包的引用
包的引用有四種格式,下面以 fmt 包為例來分別演示一下這四種格式。
**1) 標準引用格式**
```
import "fmt"
```
此時可以用fmt.作為前綴來使用 fmt 包中的方法,這是常用的一種方式。
```
package main
import "fmt"
func main() {
fmt.Println("hello world")
}
```
**2) 自定義別名引用格式**
在導入包的時候,我們還可以為導入的包設置別名
```
import F "fmt"
```
其中 F 就是 fmt 包的別名,使用時我們可以使用F.來代替標準引用格式的fmt.來作為前綴使用 fmt 包中的方法
```
package main
import F "fmt"
func main() {
F.Println("hello world")
}
```
**3) 省略引用格式**
```
import . "fmt"
```
這種格式相當于把 fmt 包直接合并到當前程序中,在使用 fmt 包內的方法是可以不用加前綴fmt.,直接引用。
```
package main
import . "fmt"
func main() {
//不需要加前綴 fmt.
Println("hello world")
}
```
**4) 匿名引用格式**
在引用某個包時,如果只是希望執行包初始化的 init 函數,而不使用包內部的數據時,可以使用匿名引用格式
```
import _ "fmt"
```
匿名導入的包與其他方式導入的包一樣都會被編譯到可執行文件中。
使用標準格式引用包,但是代碼中卻沒有使用包,編譯器會報錯。如果包中有 init 初始化函數,則通過import _ "包的路徑" 這種方式引用包,僅執行包的初始化函數,即使包沒有 init 初始化函數,也不會引發編譯器報錯。
注意:
- 一個包可以有多個 init 函數,包加載時會執行全部的 init 函數,但并不能保證執行順序,所以不建議在一個包中放入多個 init 函數,將需要初始化的邏輯放到一個 init 函數里面。
- 包的重復引用是允許的,比如包 a 引用了包 b 和包 c,包 b 和包 c 都引用了包 d。這種場景相當于重復引用了 d,這種情況是允許的,并且 Go 編譯器保證包 d 的 init 函數只會執行一次。