大家現在go項目如何管理的?一個項目是一個gopath下的包,還是一個新的gopath?

再用go做開發,在考慮項目結構如何管理,目前有兩個組織方式

一:

一個項目作為一個gopath,使用gvp和gpm管理。

二:

一個項目作為當前gopath的一個包,使用vendor機制,glide控制版本。

個人觀點如下:

一:

構建清晰,一個項目就是一個gopath,install還是任何命令很方便,go get也沒什麼關係,唯一遺憾的是官方go get 不只支持版本號,因此需要第三方gpm等工具管理依賴版本,這樣管理 任何配置文件,模板等文件直接放在bin目錄,代碼乾淨,層次分明。

二:

無需切換gopath,外部情況下可以安裝全局工具,例如gofmt等工具很輕鬆,無需額外步驟。遺憾的是vendor機制導致gopath目錄臃腫。

大家又是如何看待vendor機制的呢?

大家現在go項目如何管理的?一個項目是一個gopath下的包,還是一個新的gopath?

(gvp+gpm VS glide)


全局一個 gopath 和 每個項目一個單獨的 gopath, 各有優缺點.

針對2種選擇, 各推薦一個較優實踐(歡迎分享更好的做法).

golang 官方文檔里的選擇:

https://golang.org/doc/code.html

對應中文文檔:

如何使用Go編程

stackoverflow 上兩種選擇, 也是一半一半.

Whats a good best practice with Go workspaces?

------------------------ 全局一個 gopath 做法 -------------------------------------

我個人開發環境是設置一個 gopath, 配合 glide 管理.

全局一個 gopath 較優方案:

github管理源碼 + glide(go 包管理工具)管理依賴包

glide 介紹:

1.是一個 golang 的包管理工具.

2. 功能類似 Python 的 pip + virtualenv. (個人理解)

3. 可以鎖定項目版本, 會在當前工程目錄創建 vendor 目錄, 存放所有依賴包.(可認為是個虛擬隔離環境)

4. 默認優先從 vendor 下搜索依賴, 找不到, 再從全局 gopath 找.

5. 這樣不會污染全局的包(避免各項目依賴包版本衝突問題).

glide 工具: GitHub - Masterminds/glide: Package Management for Golang

用法:

Getting Started

Golang 套件管理工具 Glide

glide使用 - golang

如何實踐, 可以參考 gogs 項目對 glide 的應用:

GitHub - gogits/gogs: Gogs (Go Git Service) is a painless self-hosted Git service.

------------------------ 每個項目設置一個 gopath 推薦做法 ------------------------

per 項目 per gopath 推薦做法:

使用如下 腳本, 初始化.(非原創)

優點:

1. 自動創建 項目目錄結構.

2. 每個項目都是設置臨時的 gopath, 避免污染全局的 gopath, 屬於隨用隨初始化, 用完就扔那種.

用法:

保存如下腳本內容到: create_go_proj.sh

執行如下命令, 創建項目初始工程目錄:

sh ./create_go_proj.sh myproject

#!/bin/bash

#########################################################
# Module : mk_go_pro.sh
# Author : Blair Zhong
# Created : 2013.07.23
# Modify :
# Version : 1.0
# Useage : ./mk_go_pro.sh
# ./mk_go_pro.sh porject_name
# Description: 創建一個go可編譯的工程
#————————————–————————————–
#
# 根據 Go語言學習園地博客的帖子編寫,如有侵權請聯繫本人
# http://blog.studygolang.com/2012/12/go項目的目錄結構/
#
# 默認情況下運行本程序,會生成如下目錄和文件:
# test
# ├── bin
# ├── install.sh
# ├── pkg
# └── src
# ├── config
# │ └── config.go
# └── test
# └── main.go
#————————————–————————————–
# 5 directories, 3 files
#
# 其中:
# 1, install.sh為安裝文件,
# 2, config.go為test項目的配置文件
# 3, main.go這個你懂的
#
# 生成完畢之後運行進入test目錄,運行install.sh會生成如下文件和目錄
# ├── bin
# │ └── test
# ├── install.sh
# ├── pkg
# │ └── darwin_amd64
# │ └── config.a
# └── src
# ├── config
# │ └── config.go
# └── test
# └── main.go
# 6 directories, 5 files
#
# 多了兩個文件
# 1, bin目錄下的test,這個是可執行穩健
# 2, pkg/darwin_amd64下的config.a,這個是config編譯後產生的文件
#
# enjoy it!
#########################################################

PWD=$(pwd)
cd $PWD

if [[ "$1" = "" ]]; then
echo "Useage: ./mk_go_pro.sh porject_name"
echo -ne "Please input the Porject Name[test]"
read Answer
if [ "$Answer" = "" ]; then
echo -e "test";
PRO_NAME=test;
else
PRO_NAME=$Answer;
fi
else
PRO_NAME=$1;
fi

#########################################################

#創建目錄
echo "Init Directory …"
mkdir -p $PRO_NAME/bin
mkdir -p $PRO_NAME/pkg
mkdir -p $PRO_NAME/src/config
mkdir -p $PRO_NAME/src/$PRO_NAME

#########################################################
#創建 install.sh 文件
echo "Create install/install.sh …"
cd $PRO_NAME
echo "#!/bin/bash" &> install.sh
echo "if [ ! -f install.sh ]; then" &>&> install.sh
echo "echo "install must be run within its container folder" 1&>2" &>&> install.sh
echo "exit 1" &>&> install.sh
echo "fi" &>&> install.sh
echo &>&> install.sh
echo "CURDIR=`pwd`" &>&> install.sh
echo "OLDGOPATH="$GOPATH"" &>&> install.sh
echo "export GOPATH="$CURDIR"" &>&> install.sh
echo &>&> install.sh
echo "gofmt -w src" &>&> install.sh
echo "go install $PRO_NAME" &>&> install.sh
echo "export GOPATH="$OLDGOPATH"" &>&> install.sh
echo &>&> install.sh
echo "echo "finished"" &>&>install.sh
chmod +x install.sh

#創建 config.go 文件
echo "Create src/config/config.go …"
cd src/config
echo package config &> config.go
echo &>&> config.go
echo func LoadConfig() { &>&> config.go
echo &>&> config.go
echo "}" &>&> config.go

#創建 main.go
echo "Create src/$PRO_NAME/main.go …"
cd ../$PRO_NAME/
echo "package main" &> main.go
echo &>&> main.go
echo "import (" &>&> main.go
echo " "config"" &>&> main.go
echo " "fmt"" &>&> main.go
echo ")" &>&> main.go
echo &>&> main.go
echo "func main() {" &>&> main.go
echo " config.LoadConfig()" &>&> main.go
echo " fmt.Println("Hello $PRO_NAME!")" &>&> main.go
echo "}" &>&> main.go
echo "All Done!"

附: 原腳本來源 Go項目的目錄結構 —— Go語言學習園地博客


試試 Gogradle: blindpirate/gogradle ,我寫的一個包管理工具,提供項目級的GOPATH、版本號,傳遞性依賴、自動衝突解決、依賴鎖定,以及和glide相同的扁平化機制。它不需要預先設置GOPATH,構建過程中會自動把依賴包拖到項目目錄下然後啟動一個go進程,傳遞項目級別的GOPATH。

另外它提供了一些自動切換牆內源的特性。


推薦閱讀:

前端學習路線圖?
LinkedIn 的強點在哪裡,為什麼FLAG會並列 ?
如何看待樂視414硬體免費日,對以後電視,手機行業有什麼影響?
如何一句話概括一些編程技能?
求大神告訴我,該怎麼追程序猿啊不尷尬~?

TAG:IT行業 | Go語言 | gopath | golang最佳實踐 |