《Go語言實戰(zhàn)》筆記(一)|Go包管理

申金鑫? 17101223365

轉(zhuǎn)載自知乎專欄 Go語言實戰(zhàn)筆記

【嵌牛導(dǎo)讀】:本教程詳細(xì)介紹了Go語言的一些包的使用

【嵌牛鼻子】: Go 語言

【嵌牛提問】:如何使用Go語言的包

【嵌牛正文】:

前兩天一直關(guān)注的《Go語言實戰(zhàn)》終于拿到手了,這本書期待了很久樟蠕,預(yù)售的時候就第一時間進(jìn)行了預(yù)定贮聂。昨天閑暇時間翻了前三章,覺得還不錯寨辩,所以打算針對該書籍吓懈,寫一個讀書筆記系列,這是對自己看書的一個總結(jié)靡狞,也是和大家一個分享耻警。

這本是In Action系列的書籍,這個系列做研發(fā)的都知道甸怕,在研發(fā)屆評價很多甘穿,很多新的技術(shù)、語言等都會有一本實戰(zhàn)的書籍梢杭。既然是實戰(zhàn)温兼,那么這本書假設(shè)了他的讀者有了一定的基礎(chǔ),比如這本書的讀者要有一定的Go語言基礎(chǔ)武契,比如Go開發(fā)環(huán)境搭建妨托,Go的內(nèi)置類型、Go的常用關(guān)鍵字等等吝羞。

不過我公眾號[flysnow_org]里兰伤,既然打算出一個《Go語言實戰(zhàn)》的讀書筆記,就不需要大家有Go基礎(chǔ)了钧排,書里沒講的知識點敦腔,我也會在我的讀書筆記里介紹,當(dāng)然還有深入恨溜。

什么是Go語言中的包

這里我們直接講Go語言實戰(zhàn)的筆記符衔,就不介紹Go語言的入門了找前,要入門,可以參考我的這篇文章 Go語言開發(fā)環(huán)境搭建詳解

我們在使用其他語言判族,比如Java躺盛,是有包的概念的,它是Java語言中組織我們的Java文件的一個概念形帮,比如java.lang這個包槽惫,他里面有很多我們常用的類,比如String辩撑。在Go語言中界斜,包也是類似的概念,它是把我們的go文件組織起來合冀,可以方便進(jìn)行歸類各薇、復(fù)用等目的。 比如Go內(nèi)置的net包

net

├── http

├── internal

├── mail

├── rpc

├── smtp

├── testdata

├── textproto

└── url

以上是net包的一個目錄結(jié)構(gòu)君躺,net本身是一個包峭判,net目錄下的http又是一個包。從這個大家可以看到棕叫,go語言的包其實就是我們計算機里的目錄林螃,或者叫文件夾,通過它們進(jìn)行目錄結(jié)構(gòu)和文件組織谍珊,go只是對目錄名字做了一個翻譯治宣,叫【包】而已。比如這里的net包其實就是net目錄砌滞,http包其實就是http目錄侮邀,這也是go語言中的一個命名習(xí)慣,包名和文件所在的目錄名是一樣的贝润。

包的命名

go語言的包的命名绊茧,遵循簡潔、小寫打掘、和go文件所在目錄同名的原則华畏,這樣就便于我們引用,書寫以及快速定位查找尊蚁。

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

package main

import "net/http"

func main() {

? ? http.ListenAndServe("127.0.0.1:80",handler);

}

從這個例子可以看到,我們導(dǎo)入的是net/http,這在go里叫做全路徑,因為http包在net里面晰甚,net是最頂級的包衙传,所以必須使用全路徑導(dǎo)入,go編譯程序才能找到http這個包厕九,和我們文件系統(tǒng)的目錄路徑是一樣的蓖捶。

因為有了全路徑,所以命名的包名可以和其他庫的一樣扁远,只要它們的全路徑不同就可以了俊鱼,使用全路徑的導(dǎo)入,也增加了包名命名的靈活性穿香。

對于自己或者公司開發(fā)的程序而言亭引,我們一般采用域名作為頂級包名的方式绎速,這樣就不用擔(dān)心和其他開發(fā)者包名重復(fù)的問題了皮获,比如我的個人域名是飛雪無情的博客 | 專注于Android、Java纹冤、移動互聯(lián)網(wǎng)洒宝、項目管理、軟件架構(gòu),那么我自己開發(fā)的go程序都以flysnow.org作為全路徑中的最頂層部分萌京,比如導(dǎo)入我開發(fā)的一個工具包:

package main

import "flysnow.org/tools"

如果你沒有自己的域名雁歌,怎么辦呢?這時候可以使用http://github.com知残。干研發(fā)這一行的靠瞎,在github都會有個賬號,如果沒有趕緊申請一個求妹,這時候我們就可以使用http://github.com/<username>作為你的頂級路徑了乏盐,別人是不會和你重名的。

package main

import "github.com/rujews/tools"

這就是換成http://github.com命名的方式制恍。

main包

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

一個main的包,一定會包含一個main()函數(shù)鹃唯,這種我們也不陌生爱榕,比如C和Java都有main()函數(shù),它是一個程序的入口,沒這個函數(shù)坡慌,程序就無法執(zhí)行黔酥。

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

我們看一個Hello World的Go語言版本趴酣,來說明main 包。

package main

import "fmt"

func main() {

? ? fmt.Println("Hello, 世界")

}

假設(shè)該go文件叫hello.go,放在$GOPATH/src/hello目錄下坑夯,那么我們在這個目錄下執(zhí)行g(shù)o build命令就會生成二進(jìn)制的可執(zhí)行文件岖寞,在window系統(tǒng)下生成的是hello.exe,在Unix柜蜈,MAC和Linux下生成的是hello,我們在CMD或者終端里執(zhí)行它仗谆,就可以看到控制臺打印的:

Hello, 世界

二進(jìn)制可執(zhí)行文件的名字,就是該main包的go文件所在目錄的名字淑履,因為hello.go在hello目錄下隶垮,所以生成的可執(zhí)行文件就是hello這個名字。

導(dǎo)入包

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

import "fmt"

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

import (

? ? "net/http"

? ? "fmt"

)

使用一對括號包含的導(dǎo)入塊,每個包獨占一行镰绎。

對于多于一個路徑的包名脓斩,在代碼中引用的時候,使用全路徑最后一個包名作為引用的包名跟狱,比如net/http,我們在代碼使用的是http俭厚,而不是net。

現(xiàn)在我導(dǎo)入了包驶臊,那么編譯的時候挪挤,go編譯器去什么位置找他們呢?這里就要介紹下Go的環(huán)境變量了关翎。Go有兩個很重要的環(huán)境變量GOROOT和GOPATH,這是兩個定義路徑的環(huán)境變量扛门,GOROOT是安裝Go的路徑,比如/usr/local/go纵寝;GOPATH是我們自己定義的開發(fā)者個人的工作空間论寨,比如/home/flysnow/go。

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

值得了解的是:對于包的查找火焰,是有優(yōu)先級的劲装,編譯器會優(yōu)先在GOROOT里搜索,其次是GOPATH,一旦找到昌简,就會馬上停止搜索占业。如果最終都沒找到,就報編譯異常了纯赎。

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

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

import "github.com/spf13/cobra"

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

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

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

命名導(dǎo)入

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

package main

import (

? ? "fmt"

? ? myfmt "mylib/fmt"

)

func main() {

? ? fmt.Println()

? ? myfmt.Println()

}

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

Go語言規(guī)定让簿,導(dǎo)入的包必須要使用敬察,否則會包編譯錯誤,這是一個非常好的規(guī)則尔当,因為這樣可以避免我們引用很多無用的代碼而導(dǎo)致的代碼臃腫和程序的龐大莲祸,因為很多時候,我們都不知道哪些包是否使用椭迎,這在C和Java上會經(jīng)常遇到锐帜,有時候我們不得不借助工具來查找我們沒有使用的文件、類型畜号、方法和變量等缴阎,把它們清理掉。

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

package main

import (

? ? _ "mylib/fmt"

)

包的init函數(shù)

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

我們以數(shù)據(jù)庫的驅(qū)動為例绳锅,Go語言為了統(tǒng)一關(guān)于數(shù)據(jù)庫的訪問西饵,使用databases/sql抽象了一層數(shù)據(jù)庫的操作,可以滿足我們操作MYSQL鳞芙、Postgre等數(shù)據(jù)庫眷柔,這樣不管我們使用這些數(shù)據(jù)庫的哪個驅(qū)動期虾,編碼操作都是一樣的,想換驅(qū)動的時候驯嘱,就可以直接換掉镶苞,而不用修改具體的代碼。

這些數(shù)據(jù)庫驅(qū)動的實現(xiàn)鞠评,就是具體的茂蚓,可以由任何人實現(xiàn)的武翎,它的原理就是定義了init函數(shù)毕籽,在程序運行之前,把實現(xiàn)好的驅(qū)動注冊到sql包里溉躲,這樣我們就使用使用它操作數(shù)據(jù)庫了负乡。

package mysql

import (

? ? "database/sql"

)

func init() {

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

}

因為我們只是想執(zhí)行這個mysql包的init方法牍白,并不想使用這個包,所以我們在導(dǎo)入這個包的時候抖棘,需要使用_重命名包名茂腥,避免編譯錯誤。

import "database/sql"

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

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

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

這里關(guān)于Go包管理使用的就結(jié)束了诊杆,后面會接著講Go的一些常用工具、文檔以及依賴管理何陆。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市豹储,隨后出現(xiàn)的幾起案子贷盲,更是在濱河造成了極大的恐慌,老刑警劉巖剥扣,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件巩剖,死亡現(xiàn)場離奇詭異,居然都是意外死亡钠怯,警方通過查閱死者的電腦和手機佳魔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來晦炊,“玉大人鞠鲜,你說我怎么就攤上這事宁脊。” “怎么了贤姆?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵榆苞,是天一觀的道長。 經(jīng)常有香客問我霞捡,道長坐漏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任碧信,我火速辦了婚禮赊琳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘砰碴。我一直安慰自己慨畸,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布衣式。 她就那樣靜靜地躺著寸士,像睡著了一般。 火紅的嫁衣襯著肌膚如雪碴卧。 梳的紋絲不亂的頭發(fā)上弱卡,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天,我揣著相機與錄音住册,去河邊找鬼婶博。 笑死,一個胖子當(dāng)著我的面吹牛荧飞,可吹牛的內(nèi)容都是我干的凡人。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼叹阔,長吁一口氣:“原來是場噩夢啊……” “哼挠轴!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起耳幢,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤岸晦,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后睛藻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體启上,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年冈在,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片按摘。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡包券,死狀恐怖纫谅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情兴使,我是刑警寧澤系宜,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站发魄,受9級特大地震影響盹牧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜励幼,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一汰寓、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧苹粟,春花似錦有滑、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至苛秕,卻和暖如春肌访,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背艇劫。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工吼驶, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人店煞。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓蟹演,卻偏偏與公主長得像,于是被迫代替她去往敵國和親顷蟀。 傳聞我的和親對象是個殘疾皇子酒请,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容

  • 申金鑫 17101223365 轉(zhuǎn)載自公眾號flysnow_org 【嵌牛導(dǎo)讀】:本文介紹了各種系統(tǒng)下的Go語言環(huán)...
    Felixxin閱讀 3,373評論 0 20
  • 示例 包的概念、導(dǎo)入與可見性 包是結(jié)構(gòu)化代碼的一種方式:每個程序都由包(通常簡稱為 pkg)的概念組成衩椒,可以使用自...
    若與閱讀 1,441評論 0 7
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理蚌父,服務(wù)發(fā)現(xiàn),斷路器毛萌,智...
    卡卡羅2017閱讀 134,601評論 18 139
  • 要回答題目中的這個問題阁将,你要先搞清楚兩個問題: ①準(zhǔn)確,要做到什么程度才算準(zhǔn)確右遭。 ②預(yù)測做盅,是預(yù)測下一刻的股價缤削,還是...
    安定的貓閱讀 191評論 0 0
  • 當(dāng)你不知道自己為什么讓別人感到不明白是,當(dāng)你不知道為什么被冷落時吹榴,學(xué)會忍耐亭敢,因為你必須與她交往合作,這些對于你來說...
    丁海寅log閱讀 99評論 0 0