package的作用
√ package是golang最基本的分發單位和工程管理中依賴關系的體現。
√ 每個golang源代碼文件開頭都擁有一個package聲明,表示該golang代碼所屬的package。
√ 要生成golang可執行程序,必須建立一個名為main的package,並且在該package中必須包含一個名為main()的函數。
√ 在golang工程中,同一個路徑下只能存在一個package,一個package可以拆成多個源文件組成。
√ import關鍵字導入的是package路徑,而在源文件中使用package時,才需要package名。經常可見的import的目錄名和源文件中使用的package名一致容易造成import關鍵字后即是package名的錯覺,真正使用時,這兩者可以不同。

• 《Go語言編程》中calc實例
▶ 工程目錄
<calcproj>
├─<src>
├─<calc>
├─calc.go
├─<simplemath>
├─add.go
├─add_test.go
├─sqrt.go
├─sqrt_test.go
├─<bin>
├─<pkg>
▶ 詳細源碼
Δ add.go
package sm func Add(a int, b int) int { return a + b }
Δ sqrt.go
package sm import "math" func Sqrt(i int) int { v := math.Sqrt(float64(i)) return int(v) }
Δ add_test.go
package sm import "testing" func TestAdd1(t *testing.T) { r := Add(1, 2) if r != 3 { t.Errorf("Add(1, 2) failed. Got %d, expected 3.", r) } }
Δ sqrt_test.go
package sm import "testing" func TestSqrt1(t *testing.T) { v := Sqrt(16) if v != 4 { t.Errorf("Sqrt(16) failed. Got %v, expected 4.", v) } }
Δ calc.go
package main import "os" import "fmt" import "strconv" import "simplemath" var Usage = func() { fmt.Println("USAGE: calc command [arguments] ...") fmt.Println("\nThe commands are:\n\tadd\tAddition of two values.\n\tsqrt\tSquare root of a non-negative value.") } func main() { args := os.Args if args == nil || len(args) < 2 { Usage() return } switch args[1] { case "add": if len(args) != 4 { fmt.Println("USAGE: calc add <integer1> <integer2>") return } v1, err1 := strconv.Atoi(args[2]) v2, err2 := strconv.Atoi(args[3]) if err1 != nil || err2 != nil { fmt.Println("USAGE: calc add <integer1> <integer2>") return } ret := sm.Add(v1, v2) fmt.Println("Result: ", ret) case "sqrt": if len(args) != 3 { fmt.Println("USAGE: calc sqrt <integer>") return } v, err := strconv.Atoi(args[2]) if err != nil { fmt.Println("USAGE: calc sqrt <integer>") return } ret := sm.Sqrt(v) fmt.Println("Result: ", ret) default: Usage() } }
▶ 源碼說明
calcproj工程中src\simplemath目錄下只存在sm一個package,而sm包由四個源文件構成。calc.go文件中可以看到import導入的是simplemath而非sm,而在使用sm包中的Add和Sqrt函數時,使用的才是真正的包名sm。
import關鍵字
√ 使用import語句導入源代碼文件所依賴的package路徑。
√ 不得導入源代碼文件中沒有用到的package,否則golang編譯器會報編譯錯誤。
• import語法
▶ 風格一
import "package1" import "package2" import "package3" ...
▶ 風格二
import ( "package1" "package2" "package3" ... )
• import原理

如果編譯時main包導入了其他的包,那么這些包將被依次導入。
當一個包被導入時,如果該包還導入了其它的包,那么先將其他的包導入進來,然后再對該包的包級常量和變量進行初始化,最后執行init函數(如果存在)。包的導入如上圖所示,是一個遞歸地過程,等所有被導入的包加載完畢,就會對main包中的包級常量和變量進行初始化,然后執行main包中的init函數(如果存在),最后執行main函數。
如果一個包被多個包同時導入,那么它只會被導入一次。
• import修飾操作
• 點(.)操作
點(.)操作的含義是:點(.)標識的包導入后,調用該包中函數時可以省略前綴包名。點(.)操作的語法為:
import . "package1" import . "package2" import . "package3" ...
import ( . "package1" . "package2" . "package3" ... )
下面的示例中,fmt包將使用點操作省略前綴包名,os包用法保持不變:
package main import ( . "fmt" "os" ) func main() { for _, value := range os.Args { Println(value) } }
• 別名操作
別名操作的含義是:將導入的包命名為另一個容易記憶的別名。別名操作的語法為:
import p1 "package1" import p2 "package2" import p3 "package3" ...
import ( p1 "package1" p2 "package2" p3 "package3" ... )
下面的示例中,fmt包將使用別名操作重新命名為f,os包用法保持不變:
package main import ( f "fmt" "os" ) func main() { for _, value := range os.Args { f.Println(value) } }
• 下划線(_)操作
下划線(_)操作的含義是:導入該包,但不導入整個包,而是執行該包中的init函數,因此無法通過包名來調用包中的其他函數。使用下划線(_)操作往往是為了注冊包里的引擎,讓外部可以方便地使用。下划線(_)操作的語法為:
import _ "package1" import _ "package2" import _ "package3" ...
import ( _ "package1" _ "package2" _ "package3" ... )
