包(package)
Go語言的包與文件夾一一對應,所有與包相關的操作,必須依賴於工作目錄(GOPATH)。
Go的入口main()函數所在的包叫main包。
工作目錄(GOPATH)
GOPATH是Go語言中使用的一個環境變量,它使用絕對路徑提供項目的工作目錄。
工程結構
GOPATH指定的工作目錄下,代碼總是會保存在\(GOPATH/src目錄下。在工程經過gobuild、go install或go get等指令後,會將產生的二進制可執行文件放在\)GOPATH/bin目錄下,生成的中間緩存文件會被保存在$GOPATH/pkg下。
設置、使用GOPATH
設置當前目錄爲GOPATH
export GOPATH=`pwd`
使用反引號“'”將pwd指令括起來表示命令行替換
使用export指令可以將當前目錄的值設置到環境變量GOPATH中。
在多項目中使用GOPATH
使用命令行或者使用集成開發環境編譯Go源碼時,GOPATH跟隨項目設定。
建議開發者不要設置全局的GOPATH,而是隨項目設置GOPATH
匿名導入包——只導入包但不使用包內類型和數值
import (
_ "path/to/package"
)
匿名導入的包與其他方式導入包一樣會讓導入包編譯到可執行文件中,同時,導入包也會觸發init()函數調用。
包在程序啓動前的初始化入口:init
在某些需求的設計上需要在程序啓動時統一調用程序引用到的所有包的初始化函數,如果需要通過開發者手動調用這些初始化函數,那麼這個過程可能會發生錯誤或者遺漏
init()函數的特性
- 每個源碼可以使用1個init()函數。
- init()函數會在程序執行前(main()函數執行前)被自動調用。
- 調用順序爲main()中引用的包,以深度優先順序初始化。
- 同一個包中的多個init()函數的調用順序不可預期。
- init()函數不能被其他函數調用。
包導入後的init()函數初始化順序
Go語言包會從main包開始檢查其引用的所有包,每個包也可能包含其他的包。Go編譯器由此構建出一個樹狀的包引用關係,再根據引用順序決定編譯順序,依次編譯這些包的代碼。
在運行時,被最後導入的包會最先初始化並調用init()函數。
工廠模式自動註冊————管理多個包的結構體
定義商品接口,base包中定義註冊、創建工廠方法
package base
// 負責處理註冊和使用工廠的基礎代碼,該包不會引用任何外部的包
// 定義商品接口
type Commodity interface {
Show() // 定義展示商品的方法
}
var (
// 保存註冊好的工廠信息
factoryByName = make(map[string]func() Commodity) // func() Class 調用此函數,創建一個類實例,實現的工廠內部結構體會實現Class接口
)
// 註冊一個類生成工廠
func Register(name string, factory func() Commodity) {
factoryByName[name] = factory
}
// 根據名稱創建對應的類
func Create(name string) Commodity {
if f, ok := factoryByName[name]; ok {
return f()
} else {
panic("name not found")
}
}
創建牛奶類,定義init註冊到工廠
package factory
import (
"fmt"
"test/design_mode/factory/base"
)
// 定義牛奶類
type Milk struct {
}
// 實現Commodity接口
func (c *Milk) Show(){
fmt.Println("this is a Milk")
}
func init() {
// 在啓動時註冊類工廠
base.Register("Milk",func() base.Commodity {
return new(Milk)
})
}
創建麪包類,定義init註冊到工廠
package factory
import (
"fmt"
"test/design_mode/factory/base"
)
// 定義麪包類
type Bread struct {
}
// 實現Commodity接口
func (c *Bread) Show(){
fmt.Println("this is a Bread")
}
func init() {
// 在啓動時註冊類工廠
base.Register("Bread",func() base.Commodity {
return new(Bread)
})
}
使用工廠實例
package main
import (
"test/design_mode/factory/base"
_ "test/design_mode/factory" // 匿名引用包,自動註冊
)
func main() {
c1 := base.Create("Milk")
c1.Show()
c2 := base.Create("Bread")
c2.Show()
}
執行結果
$ go run design_mode/main.go
this is a Milk
this is a Bread