Go語言之包管理

什么是 Go 語言中的包

公司主營(yíng)業(yè)務(wù):網(wǎng)站制作、成都網(wǎng)站制作、移動(dòng)網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭(zhēng)能力。創(chuàng)新互聯(lián)公司是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶帶來驚喜。創(chuàng)新互聯(lián)公司推出中山免費(fèi)做網(wǎng)站回饋大家。

我們?cè)谑褂闷渌Z言,比如 Java ,是有包的概念的。它是 Java 語言中組織我們的 Java 文件的一個(gè)概念,比如java.lang這個(gè)包,它里面有很多我們常用的類,比如 String。在 Go 語言中,包也是類似的概念。它是把我們的 Go 文件組織起來,可以方便進(jìn)行歸類、復(fù)用等, 比如 Go 內(nèi)置的 net 包。


net
├── http
├── internal
├── mail
├── rpc
├── smtp
├── testdata
├── textproto
└── url


以上是 net 包的一個(gè)目錄結(jié)構(gòu),net 本身是一個(gè)包,net 目錄下的 http 又是一個(gè)包。從這個(gè)大家可以看到,Go 語言的包其實(shí)就是我們計(jì)算機(jī)里的目錄,或者叫文件夾,通過它們進(jìn)行目錄結(jié)構(gòu)和文件組織。Go 只是對(duì)目錄名字做了一個(gè)翻譯,叫“包”而已。比如這里的 net 包其實(shí)就是 net 目錄,http 包其實(shí)就是 http 目錄,這也是 Go 語言中的一個(gè)命名習(xí)慣,包名和文件所在的目錄名是一樣的。


包的命名


Go 語言中包的命名,遵循簡(jiǎn)潔、小寫以及與 Go 文件所在目錄同名的原則,這樣就便于我們引用、書寫和快速定位查找。


比如 Go 自帶的 http 這個(gè)包,這個(gè) http 目錄下的所有 Go 文件都屬于這個(gè) http 包,所以我們使用 http 包里的函數(shù)、接口的時(shí)候,導(dǎo)入這個(gè) http 包就可以了。


package main

import "net/http"

func main() {
    http.ListenAndServe("127.0.0.1:80",handler);
}


從這個(gè)例子可以看到,我們導(dǎo)入的是net/http,這在 Go 語言里叫做全路徑。因?yàn)?http 包在 net 里面,net 是最頂級(jí)的包,所以必須使用全路徑導(dǎo)入,Go 編譯程序才能找到 http 這個(gè)包,和我們文件系統(tǒng)的目錄路徑是一樣的。


因?yàn)橛辛巳窂?,所以命名的包名可以和其他?kù)的一樣,只要它們的全路徑不同就可以了。使用全路徑的導(dǎo)入,也增加了包名命名的靈活性。


對(duì)于個(gè)人或者公司開發(fā)的程序而言,我們一般采用域名作為頂級(jí)包名的方式,這樣就不用擔(dān)心和其他開發(fā)者包名重復(fù)的問題了,比如我的個(gè)人域名是www.flysnow.org,那么我自己開發(fā)的 Go 程序都以flysnow.org作為全路徑中的最頂層部分。例如,導(dǎo)入我開發(fā)的一個(gè)工具包:


package main

import "flysnow.org/tools"


如果你沒有自己的域名,怎么辦呢?這時(shí)候可以使用 Github.com 。干研發(fā)這一行的,在 Github 都會(huì)有個(gè)賬號(hào),如果沒有趕緊申請(qǐng)一個(gè)。這時(shí)候我們就可以使用github.com/<username>作為你的頂級(jí)路徑了,別人是不會(huì)和你重名的。


package main

import "github.com/rujews/tools"


這就是換成 Github.com 命名的方式。


main包


當(dāng)把一個(gè) Go 文件的包名聲明為main時(shí),就等于告訴 Go 編譯程序,我這個(gè)是一個(gè)可執(zhí)行的程序,那么 Go 編譯程序就會(huì)嘗試把它編譯為一個(gè)二進(jìn)制的可執(zhí)行文件。


一個(gè)main的包,一定會(huì)包含一個(gè)main()函數(shù),這種我們也不陌生,比如 C 和 Java 都有main()函數(shù),它是一個(gè)程序的入口,沒這個(gè)函數(shù),程序就無法執(zhí)行。


在 Go 語言里,同時(shí)要滿足main包和包含main()函數(shù),才會(huì)被編譯成一個(gè)可執(zhí)行文件。


我們看一個(gè) Hello World 的 Go 語言版本,來說明main 包。


package main

import "fmt"

func main() {
    fmt.Println("Hello, 世界")
}


假設(shè)該 Go 文件叫 hello.go,放在$GOPATH/src/hello目錄下,那么我們?cè)谶@個(gè)目錄下執(zhí)行go build命令就會(huì)生成二進(jìn)制的可執(zhí)行文件,在 window 系統(tǒng)下生成的是hello.exe;在 UINX、MAC 和 Linux 下生成的是hello,我們?cè)?CMD 或者終端里執(zhí)行它,就可以看到控制臺(tái)打印的:


Hello, 世界


二進(jìn)制可執(zhí)行文件的名字,就是該 main 包的 Go 文件所在目錄的名字,因?yàn)?hello.go 在 hello 目錄下,所以生成的可執(zhí)行文件就是 hello 這個(gè)名字。


導(dǎo)入包


要想使用一個(gè)包,必須先導(dǎo)入它才可以使用。Go 語言提供了import關(guān)鍵字來導(dǎo)入一個(gè)包,這個(gè)關(guān)鍵字告訴 Go 編譯器到磁盤的哪里去找要想導(dǎo)入的包,所以導(dǎo)入的包必須是一個(gè)全路徑的包,也就是包所在的位置。


import "fmt"


這就表示我們導(dǎo)入了fmt包,也就等于告訴 Go 編譯器,我們要使用這個(gè)包下面的代碼。如果要導(dǎo)入多個(gè)包怎么辦呢?Go 語言還為我們提供了導(dǎo)入塊。


import (
    "net/http"
    "fmt"
)


使用一對(duì)括號(hào)包含導(dǎo)入塊,每個(gè)包獨(dú)占一行。


對(duì)于多于一個(gè)路徑的包名,在代碼中引用的時(shí)候,使用全路徑最后一個(gè)包名作為引用的包名,比如net/http,我們?cè)诖a使用的是http,而不是net。


現(xiàn)在我導(dǎo)入了包,那么編譯的時(shí)候,Go 編譯器去什么位置找它們呢?這里就要介紹一下 Go 的環(huán)境變量了。Go 有兩個(gè)很重要的環(huán)境變量GOROOTGOPATH,這是兩個(gè)定義路徑的環(huán)境變量,GOROOT是安裝 Go 的路徑,比如/usr/local/go;GOPATH是我們自己定義的開發(fā)者個(gè)人的工作空間,比如/home/flysnow/go。 


編譯器會(huì)使用我們?cè)O(shè)置的這兩個(gè)路徑,再加上import導(dǎo)入的相對(duì)全路徑來查找磁盤上的包,比如我們導(dǎo)入的fmt包,編譯器最終找到的是/usr/local/go/fmt這個(gè)位置。


值得了解的是:首先,對(duì)于包的查找是有優(yōu)先級(jí)的,編譯器會(huì)優(yōu)先在GOROOT里搜索;其次是GOPATH,一旦找到,就會(huì)馬上停止搜索。如果最終都沒找到,那么就報(bào)編譯異常了。


遠(yuǎn)程包導(dǎo)入


互聯(lián)網(wǎng)的時(shí)代,現(xiàn)在大家使用類似于 Github 共享代碼的越來越多,如果有的 Go 包共享在 Github 上,我們一樣有辦法使用它們,這就是遠(yuǎn)程導(dǎo)入包了,或者是網(wǎng)絡(luò)導(dǎo)入,Go 天生就支持這種情況,所以我們可以很隨意地使用 Github 上的 Go 庫(kù)開發(fā)程序。


import "github.com/spf13/cobra"


這種導(dǎo)入,前提必須是該包托管在一個(gè)分布式的版本控制系統(tǒng)上,比如 Github、Bitbucket 等,并且是 Public 的權(quán)限,可以讓我們直接訪問它們。


編譯在導(dǎo)入它們的時(shí)候,會(huì)先在GOPATH下搜索這個(gè)包,如果沒有找到,就會(huì)使用go get工具從版本控制系統(tǒng)(GitHub)獲取,并且會(huì)把獲取到的源代碼存儲(chǔ)在GOPATH目錄下對(duì)應(yīng) URL 的目錄里,以供編譯使用。


go get工具可以遞歸獲取依賴包,如果github.com/spf13/cobra也引用了其他的遠(yuǎn)程包,該工具可以一并下載下來。


命名導(dǎo)入


我們知道,在使用import關(guān)鍵字導(dǎo)入包之后,我們就可以在代碼中通過包名使用該包下相應(yīng)的函數(shù)、接口等。如果我們導(dǎo)入的包名正好有重復(fù)的怎么辦呢?針對(duì)這種情況,Go 語言可以讓我們對(duì)導(dǎo)入的包重新命名,這就是命名導(dǎo)入。


package main

import (
    "fmt"
    myfmt "mylib/fmt"
)

func main() {
    fmt.Println()
    myfmt.Println()
}


如果沒有重新命名,那么對(duì)于編譯器來說,這兩個(gè)fmt它是區(qū)分不清楚的。重命名也很簡(jiǎn)單,在我們導(dǎo)入的時(shí)候,在包名的左側(cè),起一個(gè)新的包名就可以了。


Go 語言規(guī)定,導(dǎo)入的包必須要使用,否則會(huì)包編譯錯(cuò)誤,這是一個(gè)非常好的規(guī)則,因?yàn)檫@樣可以避免我們引用很多無用的代碼而導(dǎo)致的代碼臃腫和程序的龐大。很多時(shí)候,我們都不知道哪些包是否使用,這在 C 和 Java 上會(huì)經(jīng)常遇到,因此我們不得不借助工具來查找我們沒有使用的文件、類型、方法和變量等,把它們清理掉。


但是有時(shí)候,我們需要導(dǎo)入一個(gè)包,但是又不使用它,按照規(guī)則,這是不行的,為此 Go 語言給我們提供了一個(gè)空白標(biāo)志符 _ ,只需要我們使用 _ 重命名我們導(dǎo)入的包就可以了。


package main

import (
    _ "mylib/fmt"
)


包的 init ()函數(shù)


每個(gè)包都可以有任意多個(gè)init()函數(shù),這些init()函數(shù)都會(huì)在main()函數(shù)之前執(zhí)行。init()函數(shù)通常用來做初始化變量、設(shè)置包或者其他需要在程序執(zhí)行前的引導(dǎo)工作。比如上面我們講的需要使用 _ 空標(biāo)志符來導(dǎo)入一個(gè)包的目的,就是想執(zhí)行這個(gè)包里的init()函數(shù)。


我們以數(shù)據(jù)庫(kù)的驅(qū)動(dòng)為例,Go 語言為了統(tǒng)一關(guān)于數(shù)據(jù)庫(kù)的訪問,使用databases/sql抽象了一層數(shù)據(jù)庫(kù)的操作,可以滿足我們操作 MySQL、Postgre 等數(shù)據(jù)庫(kù)。這樣不管我們使用這些數(shù)據(jù)庫(kù)的哪個(gè)驅(qū)動(dòng),編碼操作都是一樣的,想換驅(qū)動(dòng)的時(shí)候,就可以直接換掉,而不用修改具體的代碼。


這些數(shù)據(jù)庫(kù)驅(qū)動(dòng)的實(shí)現(xiàn),就是具體的,可以由任何人實(shí)現(xiàn)的,它的原理就是定義了init()函數(shù),在程序運(yùn)行之前,把實(shí)現(xiàn)好的驅(qū)動(dòng)注冊(cè)到 sql 包里,這樣我們就使用使用它操作數(shù)據(jù)庫(kù)了。


package mysql

import (
    "database/sql"
)

func init() {
    sql.Register("mysql", &MySQLDriver{})
}


因?yàn)槲覀冎皇窍雸?zhí)行這個(gè) mysql 包的init()方法,并不想使用這個(gè)包,所以我們?cè)趯?dǎo)入這個(gè)包的時(shí)候,需要使用_重命名包名,避免編譯錯(cuò)誤。


import "database/sql"
import _ "github.com/go-sql-driver/mysql"

db, err := sql.Open("mysql", "user:password@/dbname")


看非常簡(jiǎn)潔,剩下針對(duì)的數(shù)據(jù)庫(kù)的操作都是使用的database/sql標(biāo)準(zhǔn)接口。如果我們想換一個(gè) mysql 的驅(qū)動(dòng)的話,只需要換個(gè)導(dǎo)入就可以了,靈活方便,這也是面向接口編程的便利。

新聞標(biāo)題:Go語言之包管理
新聞來源:http://bm7419.com/article30/pccipo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站制作、商城網(wǎng)站、移動(dòng)網(wǎng)站建設(shè)、全網(wǎng)營(yíng)銷推廣服務(wù)器托管、網(wǎng)站導(dǎo)航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站優(yōu)化排名