go項目部署詳解


https://blog.csdn.net/u010003835/article/details/51896018

 

Go的官網文檔How to Write Go Code中,已經介紹了Go的項目目錄一般包含以下幾個:

  • src 包含項目的源代碼文件;
  • pkg 包含編譯后生成的包/庫文件;
  • bin 包含編譯后生成的可執行文件。

可以通過下面的例子來說明工程目錄的組織管理。(Windows 7 64位,go version go1.3.3 windows/amd64)

1. 創建一個庫文件

創建一個庫文件a.go並保存在src目錄的一個子目錄下面。

  1.  
    package myfunc
  2.  
     
  3.  
    import "fmt"
  4.  
     
  5.  
    func Afunc(str string) {
  6.  
    fmt.Println( "a.go is package mufunc.")
  7.  
    fmt.Println(str)
  8.  
    }

這時候目錄結構如下:

  1.  
    <dirtest>
  2.  
    |-- <src>
  3.  
    |-- <mufunc>
  4.  
    |--a.go

2. 創建main

注意,如果用LITEIDE創建go項目,要編譯的主函數必須放在main包下面,否則既不提示出錯原因,也不會生成可執行文件,比較操蛋,還好最后發現了。

關於main包的位置,可以參照參考資料2,個人建議放在scr/main下面,畢竟官方推薦包名和文件存放的文件夾名稱最好相同(雖然包名和文件夾名可以不相同,也就是說一個文件夾下可以包含多個包的.go文件)。

  1.  
    package main
  2.  
     
  3.  
    import "myfunc"
  4.  
     
  5.  
    func main() {
  6.  
    myfunc.Afunc( "b.go is package main.")
  7.  
    }

這時候目錄結構如下:

  1.  
    <dirtest>
  2.  
    |-- <src>
  3.  
    |-- <mufunc>
  4.  
    |--a.go
  5.  
    |-- <main>
  6.  
    |--b.go

3. 使用go build

如果這時候使用go build,你會發現下面的輸出:

  1.  
    E:\dirtest> go build src\main\b.go
  2.  
     
  3.  
    src\main\b. go:3:8: cannot find package "myfunc" in any of:
  4.  
    C:\Program Files\ go\src\pkg\myfunc (from $GOROOT)
  5.  
    D:\GoLang\src\myfunc (from $GOPATH)

從輸出中我們可以看到,Go先是從$GOROOT中查找包myfunc,如果沒找到就從$GOPATH中查找,結果都沒有找到,我們可以使用go env輸出Go的環境變量設置:

  1.  
    E:\dirtest>go env
  2.  
     
  3.  
    set GOARCH=amd64
  4.  
    set GOBIN=
  5.  
    set GOCHAR=6
  6.  
    set GOEXE=.exe
  7.  
    set GOHOSTARCH=amd64
  8.  
    set GOHOSTOS=windows
  9.  
    set GOOS=windows
  10.  
    set GOPATH=D:\GoLang
  11.  
    set GORACE=
  12.  
    set GOROOT=C:\Program Files\go
  13.  
    set GOTOOLDIR=C:\Program Files\go\pkg\tool\windows_amd64
  14.  
    set CC=gcc
  15.  
    set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0
  16.  
    set CXX=g++
  17.  
    set CGO_ENABLED=1

顯然E:\dirtest這個目錄沒有加到$GOPATH中,在環境變量中添加該目錄:

GOPATH

保存后,重新執行(可能需要重新打開控制台,讓環境變量生效)go build,就在當前目錄生成了一個可執行文件b.exe

  1.  
    E:\dirtest\src\main>go env
  2.  
    set GOARCH=amd64
  3.  
    set GOBIN=
  4.  
    set GOCHAR=6
  5.  
    set GOEXE=.exe
  6.  
    set GOHOSTARCH=amd64
  7.  
    set GOHOSTOS=windows
  8.  
    set GOOS=windows
  9.  
    set GOPATH=D:\GoLang;E:\dirtest
  10.  
    set GORACE=
  11.  
    set GOROOT=C:\Program Files\go
  12.  
    set GOTOOLDIR=C:\Program Files\go\pkg\tool\windows_amd64
  13.  
    set CC=gcc
  14.  
    set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0
  15.  
    set CXX=g++
  16.  
    set CGO_ENABLED=1
  17.  
     
  18.  
    E:\dirtest>go build src\main\b.go
  19.  
    E:\dirtest>dir
  20.  
     
  21.  
    E:\dirtest 的目錄
  22.  
     
  23.  
    2015/01/13 23:11 <DIR> .
  24.  
    2015/01/13 23:11 <DIR> ..
  25.  
    2015/01/13 23:11 1,958,912 b.exe
  26.  
    2015/01/13 22:52 <DIR> src
  27.  
     
  28.  
    E:\dirtest>b.exe
  29.  
    a.go is package mufunc.
  30.  
    b.go is package main.

雖然成功運行,但是沒有按照期待的那樣生成在bin目錄下面。為了達到這樣的效果,你需要go install。注意go install是針對package,而不是針對單個.go文件。

但是如果是當前狀態執行go install,雖然可以成功,但你會發現,並沒有在項目根目錄E:\dirtest中創建bin\main.exe,反而是在D:\GoLang中創建了。

如果對main包執行go install呢?

  1.  
    E:\dirtest\src\main> go install
  2.  
    go install: no install location for E:\dirtest\src\main: hidden by D:\GoLang\src
  3.  
    \main

可以看到,輸出提示當前目錄被隱藏。顯然這個順序是對應$GOPATH的設置的,把$GOPATH中的路徑順序改一下:

GOPATH

然后在執行go install myfunc,發現成功地在pkg目錄下面生成了myfunc.a。同樣執行go install main,也成功的在bin目錄下生成了main.exe。此時的目錄結構如下:

  1.  
    <dirtest>
  2.  
    |-- <src>
  3.  
    |-- <mufunc>
  4.  
    |--a.go
  5.  
    |-- <main>
  6.  
    |--b.go
  7.  
    |-- <pkg>
  8.  
    |-- <windows_amd64>
  9.  
    |--myfunc.a
  10.  
    |-- <bin>
  11.  
    |--main.exe

現在就算是成功完成了一個示例“項目”吧...

4. 常見錯誤

除了上面的步驟中出現的錯誤,其實工程目錄管理稍有不慎,就會出現其他問題,例如:

1. 一個文件夾下面包含多個不同包的源文件。也就是把a.gob.go都放到myfunc目錄下面會是什么情況呢?

這時候的目錄結構如下:

  1.  
    <dirtest>
  2.  
    |-- <src>
  3.  
    |-- <mufunc>
  4.  
    |--a.go
  5.  
    |--b.go

那么執行go installgo build,甚至go run都會是相同的錯誤:

  1.  
    E:\dirtest\src\myfunc> go install
  2.  
    can 't load package: package myfunc: found packages myfunc (a.go) and main (b.go)
  3.  
    in E:\dirtest\src\myfunc
  4.  
     
  5.  
    E:\dirtest\src\myfunc>go build
  6.  
    can't load package: package myfunc: found packages myfunc (a.go) and main (b.go)
  7.  
    in E:\dirtest\src\myfunc
  8.  
     
  9.  
    E:\dirtest\src\myfunc> go run b.go
  10.  
    b. go:3:8: found packages myfunc (a.go) and main (b.go) in E:\dirtest\src\myfunc

從參考資料3中可以看到,每個子目錄中只能存在一個package,否則編譯時會報錯,所以一個子目錄下面不能包含多個不同包的源文件。

2. 一個項目能包含多個main()嗎?

簡單測試下,創建一個c.go,並使用myfunc包(沒有導入其他包的情況類似):

  1.  
    package main
  2.  
    import "fmt"
  3.  
    import "myfunc"
  4.  
     
  5.  
    func main() {
  6.  
    fmt.Println( "This is single c.go")
  7.  
    myfunc.Afunc( "c.go is also package main.")
  8.  
    }

執行相應的命令,結果如下:

  1.  
    E:\dirtest\src\main> go build
  2.  
    # main
  3.  
    .\c. go:4: main redeclared in this block
  4.  
    previous declaration at .\b. go:5
  5.  
     
  6.  
    E:\dirtest\src\main> go build c.go
  7.  
    # 成功,當前目錄下生成了c.exe
  8.  
     
  9.  
    E:\dirtest\src\main> go install
  10.  
    # main
  11.  
    .\c. go:4: main redeclared in this block
  12.  
    previous declaration at .\b. go:5
  13.  
     
  14.  
    E:\dirtest\src\main> go install c.go
  15.  
    go install: no install location for .go files listed on command line (GOBIN not
  16.  
    set)
  17.  
     
  18.  
    E:\dirtest\src\main> go run c.go
  19.  
    This is single c. go
  20.  
    a. go is package mufunc.
  21.  
    c. go is also package main.

顯然只能是go rungo build c.go可行。如果把c.go移到單獨的目錄下面呢:

  1.  
    E:\dirtest\src\cmain>dir
  2.  
     
  3.  
    E:\dirtest\src\cmain 的目錄
  4.  
     
  5.  
    2015/01/14 11:27 <DIR> .
  6.  
    2015/01/14 11:27 <DIR> ..
  7.  
    2015/01/14 11:24 147 c.go
  8.  
     
  9.  
    E:\dirtest\src\cmain> go build
  10.  
     
  11.  
    E:\dirtest\src\cmain> go install

均可以執行成功。go install在bin目錄下面生成了對應的exe文件。看來還是目錄管理的問題。

3. go install: no install location for .go files listed on command line (GOBIN not set)

從上面的示例輸出中就能看到,使用go install針對單個文件時,就會出現這個錯誤。默認情況下如果設置了$GOROOT$GOPATH,就會依次尋找$GOROOT/bin$GOPATH/bin。那么我們如果自定義設置了$GOBIN=E:\dirtest\bin之后會怎樣?

GOPATH

  1.  
    E:\dirtest\src\cmain>go env
  2.  
    set GOARCH=amd64
  3.  
    set GOBIN=E:\dirtest\bin
  4.  
    set GOCHAR=6
  5.  
    set GOEXE=.exe
  6.  
    set GOHOSTARCH=amd64
  7.  
    set GOHOSTOS=windows
  8.  
    set GOOS=windows
  9.  
    set GOPATH=E:\dirtest;D:\GoLang
  10.  
    set GORACE=
  11.  
    set GOROOT=C:\Program Files\go
  12.  
    set GOTOOLDIR=C:\Program Files\go\pkg\tool\windows_amd64
  13.  
    set CC=gcc
  14.  
    set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0
  15.  
    set CXX=g++
  16.  
    set CGO_ENABLED=1
  17.  
     
  18.  
    E:\dirtest\src\cmain>go install c.go
  19.  
    # 成功在 E:\dirtest\bin 下面生成 c.exe

雖然成功了,但是go install應該是作用於包級別,而非單個文件。

4. go build、go install 和 go run 的區別

詳細的可以查看參考資料4,這里簡單說一下:

  • go build (相當於編譯) 編譯包,如果是main包則在當前目錄生成可執行文件,其他包不會生成.a文件;
  • go instal (要設置GOBIN)編譯包,同時復制結果到$GOPATH/bin$GOPATH/pkg等對應目錄下;
  • go run gofiles...(相當於編譯並運行) 編譯列出的文件,並生成可執行文件然后執行。注意只能用於main包,否則會出現go run: cannot run non-main package的錯誤。

 

 

 

 

此外,go run是不需要設置$GOPATH的,但go buildgo install必須設置。go run常用來測試一些功能,這些代碼一般不包含在最終的項目中。

5. 總結

  1. 一定要管理好目錄
  2. 多個項目最好都在一個$GOPATH下面,即src/proj1src/proj2,etc
  3. 盡量使用go install,這樣能夠規范項目整體結構

6. 參考資料

  1. Golang項目目錄結構組織
  2. 關於main包放在哪的問題
  3. 關於golang中包(package)的二三事兒
  4. Running multi-file main package


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM