1.包的命名
go語言的包的命名,遵循簡潔、小寫、和go文件所在目錄同名的原則,這樣就便於我們引用,書寫以及快速定位查找。比如go自帶的http這個包,它這個http目錄下的所有go文件都屬於這個http包,所以我們使用http包裏的函數、接口的時候,導入這個http包就可以了。
package main
import "net/http"
func main() {
http.ListenAndServe("127.0.0.1:80",handler);
}
從這個例子可以看到,我們導入的是net/http
,這在go裏叫做全路徑,因爲http包在net裏面,net是最頂級的包,所以必須使用全路徑導入,go編譯程序才能找到http這個包,和我們文件系統的目錄路徑是一樣的。
對於自己或者公司開發的程序而言,我們一般採用域名作爲頂級包名的方式,這樣就不用擔心和其他開發者包名重複的問題了,比如我的個人域名是www.flysnow.org
,那麼我自己開發的go程序都以flysnow.org
作爲全路徑中的最頂層部分,比如導入我開發的一個工具包:
package main
import "flysnow.org/tools"
2.main 包
當把一個go文件的包名聲明爲main
時,就等於告訴go編譯程序,我這個是一個可執行的程序,那麼go編譯程序就會嘗試把它編譯爲一個二進制的可執行文件。
一個main
的包,一定會包含一個main()
函數,這種我們也不陌生,比如C和Java都有main()
函數,它是一個程序的入口,沒這個函數,程序就無法執行。
在go語言裏,同時要滿足main
包和包含main()
函數,纔會被編譯成一個可執行文件。
3.導入包
要想使用一個包,必須先導入它纔可以使用,Go語言提供了import
關鍵字來導入一個包,這個關鍵字告訴Go編譯器到磁盤的哪裏去找要想導入的包,所以導入的包必須是一個全路徑的包,也就是包所在的位置。
import "fmt"
這就表示我們導入了fmt
包,也就等於告訴go編譯器,我們要使用這個包下面的代碼。如果要導入多個包怎麼辦呢?Go語言還爲我們提供的導入塊。
import (
"net/http"
"fmt"
)
使用一對括號包含的導入塊,每個包獨佔一行
對於多於一個路徑的包名,在代碼中引用的時候,使用全路徑最後一個包名作爲引用的包名,比如net/http
,我們在代碼使用的是http
,而不是net
4.命名導入
我們知道,在使用import
關鍵字導入包之後,我們就可以在代碼中通過包名使用該包下相應的函數、接口等。如果我們導入的包名正好有重複的怎麼辦呢?針對這種情況,Go語言可以讓我們對導入的包重新命名,這就是命名導入。
package main
import (
"fmt"
myfmt "mylib/fmt" //命名導入
)
func main() {
fmt.Println()
myfmt.Println()
}
如果沒有重新命名,那麼對於編譯器來說,這兩個fmt
它是區分不清楚的。重命名也很簡單,在我們導入的時候,在包名的左側,起一個新的包名就可以了。
Go語言規定,導入的包必須要使用,否則會包編譯錯誤
但是有時候,我們需要導入一個包,但是又不使用它,按照規則,這是不行的,爲此Go語言給我們提供了一個空白標誌符_
,只需要我們使用_
重命名我們導入的包就可以了
package main
import (
_ "mylib/fmt"
)
5.包的init函數
每個包都可以有任意多個init函數,這些init函數都會在main函數之前執行。init函數通常用來做初始化變量、設置包或者其他需要在程序執行前的引導工作。比如上面我們講的需要使用_
空標誌符來導入一個包的目的,就是想執行這個包裏的init函數。
我們以數據庫的驅動爲例,Go語言爲了統一關於數據庫的訪問,使用databases/sql
抽象了一層數據庫的操作,可以滿足我們操作MYSQL、Postgre等數據庫,這樣不管我們使用這些數據庫的哪個驅動,編碼操作都是一樣的,想換驅動的時候,就可以直接換掉,而不用修改具體的代碼。
這些數據庫驅動的實現,就是具體的,可以由任何人實現的,它的原理就是定義了init函數,在程序運行之前,把實現好的驅動註冊到sql包裏,這樣我們就使用使用它操作數據庫了
package mysql
import (
"database/sql"
)
func init() {
sql.Register("mysql", &MySQLDriver{})//初始化mysql驅動
}
因爲我們只是想執行這個mysql包的init方法,並不想使用這個包,所以我們在導入這個包的時候,需要使用_
重命名包名,避免編譯錯誤。
import "database/sql"
import _ "github.com/go-sql-driver/mysql"//初始化mysql驅動
db, err := sql.Open("mysql", "user:password@/dbname")
看非常簡潔,剩下針對的數據庫的操作,都是使用的database/sql
標準接口,如果我們想換一個mysql的驅動的話,只需要換個導入就可以了,靈活方便,這也是面向接口編程的便利。