• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            牽著老婆滿街逛

            嚴(yán)以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            Go 語(yǔ)言的包依賴管理

            轉(zhuǎn)載自:https://io-meter.com/2014/07/30/go's-package-management/

            對(duì)于從 Ruby、Python 或者 Node 等編程語(yǔ)言轉(zhuǎn)向 Go 語(yǔ)言的開(kāi)發(fā)者,可能會(huì)有一個(gè)疑問(wèn): Go 語(yǔ)言中的包依賴關(guān)系是怎么管理的?有沒(méi)有什么方便使用的工具呢? 我最近研究了一下這個(gè)問(wèn)題,以下是我的研究報(bào)告。

            (圖片來(lái)源:nathany.com)(圖片來(lái)源:nathany.com)

            Go 語(yǔ)言本身提供的包管理機(jī)制

            在 Go 語(yǔ)言中,我們可以使用go get命令安裝遠(yuǎn)程倉(cāng)庫(kù)中托管的代碼,不同于 Ruby Gem、pypi 等集中式的包管理機(jī)制, Go 語(yǔ)言的包管理系統(tǒng)是去中心化的。簡(jiǎn)單來(lái)講,go get命令支持任何一個(gè)位置托管的 Git 或 Mercurial 的倉(cāng)庫(kù),無(wú)論是 Github 還是 Google Code 上的包,都可以通過(guò)這個(gè)命令安裝。

            我們知道,在 Go 語(yǔ)言中的import語(yǔ)句對(duì)于已經(jīng)使用go get安裝到本地的包,依然要使用其去絕對(duì)路徑引入。 比如對(duì)于從 Github 上安裝的 goji,其在 Github 上的路徑 URL 是 https://github.com/zenazn/goji,因此在import它的時(shí)候需要使用下面的代碼:

            1
            import "github.com/zenazn/goji"

            正因?yàn)槿绱耍珿o 語(yǔ)言可以通過(guò)直接分析代碼中的import語(yǔ)句來(lái)查詢依賴關(guān)系。 go get命令在執(zhí)行時(shí),就會(huì)自動(dòng)解析import來(lái)安裝所有的依賴。

            除了go get,Go 語(yǔ)言還提供了一個(gè) Workspace 的機(jī)制,這個(gè)機(jī)制也是很容易讓人困惑的設(shè)計(jì)。簡(jiǎn)單來(lái)說(shuō)就是通過(guò)設(shè)定 GOPATH環(huán)境變量,指定除了GOROOT所指定的目錄之外,Go 代碼所在的位置(也就是 Workspace 的位置)。 一般來(lái)說(shuō),GOPATH目錄下會(huì)包含pkgsrcbin三個(gè)子目錄,這三個(gè)目錄各有用處。

            • bin 目錄用來(lái)放置編譯好的可執(zhí)行文件,為了使得這里的可執(zhí)行文件可以方便的運(yùn)行, 在 shell 中設(shè)置PATH變量。
            • src 目錄用來(lái)放置代碼源文件,在進(jìn)行import時(shí),是使用這個(gè)位置作為根目錄的。自己編寫(xiě)的代碼也應(yīng)該放在這下面。
            • pkg 用來(lái)放置安裝的包的鏈接對(duì)象(Object)的。這個(gè)概念有點(diǎn)類似于鏈接庫(kù),Go 會(huì)將編譯出的可連接庫(kù)放在這里, 方便編譯時(shí)鏈接。不同的系統(tǒng)和處理器架構(gòu)的對(duì)象會(huì)在pkg存放在不同的文件夾中。

            我的GOPATH目錄樹(shù)如下所示:

            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            ├── bin
            ├── pkg
            │   └── darwin_amd64
            │   └── github.com
            │   └── zenazn
            │     └── goji
            └── src
            ├── code.google.com
            │   └── p
            │   └── go.crypto
            └── github.com
               └── zenazn
               └── goji

            一般來(lái)說(shuō),你自己的代碼不應(yīng)該直接放置在src目錄下,而應(yīng)該為其建立對(duì)應(yīng)的項(xiàng)目文件夾。 go get也會(huì)把第三方包的源代碼放到這個(gè)目錄下,因此一般推薦設(shè)置兩個(gè)GOPATH,比如:

            1
            export GOPATH="/usr/local/share/go:$HOME/codes/go"

            這樣第三方包就會(huì)默認(rèn)放置在第一個(gè)路徑中,而你可以在第二個(gè)路徑下編寫(xiě)自己的代碼。 雖然 Go 語(yǔ)言本身已經(jīng)提供了相當(dāng)強(qiáng)大的包管理方式了,但是仍然有一些不足:

            1. 不能很方便地隔離不同項(xiàng)目的環(huán)境
            2. 不能很方便地控制某個(gè)依賴包的版本
            3. 不能管理 Go 本身的版本

            因此我們還需要一些第三方的工具來(lái)彌補(bǔ)這些缺陷。

            第三方的管理工具

            GOPATH 管理和包管理

            由于存在GOPATH的機(jī)制,我們可以使用多個(gè)GOPATH來(lái)實(shí)現(xiàn)項(xiàng)目隔離的方法。 譬如,對(duì)于每個(gè)項(xiàng)目,都分配一個(gè)不同的路徑作為GOPATH。 可以實(shí)現(xiàn)這樣的目的的工具有gvp等。

            對(duì)于 gvp 來(lái)說(shuō),想要針對(duì)當(dāng)前目錄建立一個(gè)GOPATH,只需要執(zhí)行gvp init即可。 gvp 會(huì)在當(dāng)前項(xiàng)目的目錄下新建一個(gè)隱藏的文件夾作為GOPATH指向的位置。 切換環(huán)境時(shí)使用下面兩個(gè)命令來(lái)修改環(huán)境變量。這種做法跟 Python 中的virtualenv比較類似。

            1
            2
            source gvp in   # 進(jìn)入當(dāng)前目錄對(duì)應(yīng)的 GOPATH 環(huán)境
            source gvp out # 登出當(dāng)前目錄對(duì)應(yīng)的 GOPATH 環(huán)境

            至于對(duì)依賴包更版本更細(xì)致的管理,可以配合的工具還有 gpm。 gpm有點(diǎn)類似于 Python 中的pip工具。他可以生成一個(gè)名為 Godeps 的文件, 其中記錄了每個(gè)依賴包的 URL 以及使用的版本(hash tag)。 之前的一篇文章提到 gpm只能管理來(lái)自 Github 的依賴,不過(guò)當(dāng)前的版本已經(jīng)支持了非 Git 方式托管的依賴包了。

            基于同樣原理管理依賴包版本的工具還有Godep。 這個(gè)工具在 Github 上具有相當(dāng)高的關(guān)注度。它所生成的Godeps文件采用 JSON 格式儲(chǔ)存, 是一個(gè)跟 Node.js 中 NPM 相仿的工具。

            總體來(lái)說(shuō)以上幾個(gè)工具已經(jīng)可以解決隔離項(xiàng)目環(huán)境和控制依賴包版本的問(wèn)題了。但是使用上還不算方便, 為了能在我們 cd 到某個(gè)目錄時(shí)自動(dòng)的切換環(huán)境變量,我們可能還需要在 shell 做一些配置使其在cd到項(xiàng)目目錄下時(shí)自動(dòng)切換環(huán)境變量。

            這方面做的比較好的一個(gè)選擇是 Go Manager(gom), 它生成的Gomfile格式上幾乎跟 Ruby Gem 一樣。gom 可能是這些工具當(dāng)中使用最方便的一個(gè), 只要使用gom build命令代替原來(lái)的go build命令進(jìn)行編譯,你基本不需要配置 Shell 或者和環(huán)境變量打交道。

            Go 語(yǔ)言版本管理

            對(duì)于 Go 語(yǔ)言,一般來(lái)說(shuō)并沒(méi)有使多個(gè)語(yǔ)言版本并存的需求。Go 語(yǔ)言現(xiàn)在還沒(méi)有經(jīng)歷過(guò)類似 Python 2.x 到 3.x 或者 Ruby 1.x 到 2.x 這樣破壞性的版本升級(jí)。舊的代碼在新的語(yǔ)言版本當(dāng)中一般是能夠正確運(yùn)行的。 不過(guò)若遇到非要并存多個(gè)版本的時(shí)候,gvm就是一個(gè)不錯(cuò)的選擇。

            gvm 的使用跟 rvm 比較類似。

            1
            2
            gvm install go1 # 安裝 go1 版本
            gvm use go1 # 修改環(huán)境變量使用 go1 版本的 Go

            總結(jié)

            是否有必要使用多個(gè) Workspace 仍然具有爭(zhēng)議,譬如這個(gè) StackOverflow 上的相關(guān)問(wèn)答中, 就有人提出只使用一個(gè) Workspace 就可以應(yīng)付大多數(shù)情況了。

            在研究相關(guān)問(wèn)題的時(shí)候,我發(fā)現(xiàn)很多 Go 語(yǔ)言的用戶都還帶著原來(lái)編程語(yǔ)言的思維, 這點(diǎn)從上面介紹的多個(gè)工具的特點(diǎn)當(dāng)中就可以很容易看出來(lái):gvpgpm就是典型的 Python 的包管理模式, gvp對(duì)應(yīng)著virtualenvgpm對(duì)應(yīng)著pip;如果你之前是 Node.js 和 NPM 的用戶, 那么GoDeps肯定會(huì)讓你有種熟悉的感覺(jué);更不用說(shuō)最后介紹的gom了,它從名稱到文件格式都在模仿 Ruby Gem。

            不同編程背景的開(kāi)發(fā)者來(lái)到 Go 語(yǔ)言之后各自帶來(lái)了自己的依賴包管理方式,而且形成了各自的社區(qū)。 這種現(xiàn)象雖然使得各自圈子的開(kāi)發(fā)者免去了選擇恐懼癥,但是造成的解決方案分裂和互不兼容的情況也需要正視。 這時(shí)我們不禁要問(wèn),Go 自己的解決方式應(yīng)該是什么樣的?Go 語(yǔ)言為何沒(méi)有一個(gè)官方標(biāo)準(zhǔn)的解決方案呢?

            Go FAQ的一段文字當(dāng)中我們可以得到部分答案:

            Versioning is a source of significant complexity, especially in large code bases, and we are unaware of any approach that works well at scale in a large enough variety of situations to be appropriate to force on all Go users. (依賴包的版本管理是一個(gè)非常復(fù)雜的問(wèn)題,特別是在代碼量比較大的時(shí)候。 我們一直沒(méi)有找到任何一種方式能夠在各種情形下都能良好工作, 因此也沒(méi)有一種方式足夠好到應(yīng)該強(qiáng)迫所有的 Go 用戶使用它)

            因此現(xiàn)階段來(lái)看,對(duì)于 Go 語(yǔ)言的包管理解決方案,我們也就只能“仁者見(jiàn)仁,智者見(jiàn)智”了。

            最后,對(duì)于想要了解 Go 語(yǔ)言的包管理以及更多可用的工具的讀者,這里再推薦兩篇相關(guān)的文章: Go Package Management 和 A Journey in Golang Package Manager

            posted on 2016-12-22 21:25 楊粼波 閱讀(343) 評(píng)論(0)  編輯 收藏 引用


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            久久久综合九色合综国产| 亚洲AV无码1区2区久久| 精品久久久久久国产三级| 国产精品VIDEOSSEX久久发布| 久久久久国产精品麻豆AR影院| 久久亚洲AV永久无码精品| 亚洲欧美另类日本久久国产真实乱对白 | 中文无码久久精品| 久久婷婷五月综合国产尤物app | 性做久久久久久久| 青青国产成人久久91网| 亚洲人成网站999久久久综合 | 久久er国产精品免费观看8| 亚洲精品无码久久久久AV麻豆| 人人狠狠综合久久88成人| 99久久综合国产精品二区| 77777亚洲午夜久久多喷| 久久亚洲高清观看| 波多野结衣AV无码久久一区| 久久久精品一区二区三区| 区久久AAA片69亚洲 | 久久久久久精品无码人妻| 久久久久久久尹人综合网亚洲 | 久久人人爽人人爽人人片av高请| 99久久成人18免费网站| 亚洲狠狠婷婷综合久久蜜芽| 久久99精品久久久久久野外| 久久亚洲日韩精品一区二区三区| 久久伊人中文无码| 久久久久中文字幕| 久久无码人妻一区二区三区午夜| 欧美激情精品久久久久久| 青青草国产成人久久91网| 97久久国产露脸精品国产| 国产精品va久久久久久久| 2020久久精品国产免费| av色综合久久天堂av色综合在| 久久精品国产亚洲Aⅴ蜜臀色欲| 99久久人妻无码精品系列蜜桃| 亚洲精品乱码久久久久久久久久久久| 久久久久亚洲AV成人网|