由淺入深:一個簡單的例子,讓你吃透Go語言自定義的包管理

前言

首先使用hello world,演示Go的包是如何導入的。

<code>package main

import "fmt"

func main() {
\tfmt.Println("Hello, world")
}/<code>

其中 “fmt” 就是就是Go內置的一個包,包含與格式化和輸出到屏幕相關的各種功能。


包的好處

使用這種方式導入包,有以下3個好處:

  1. 降低函數方法重名的可能,讓函數保持簡短和簡潔。
  2. 有效地組織代碼,很方便導向到標的。
  3. 只需重新編譯小的程序塊,從而加快編譯速度。例如包fmt,我們不必在每次更改程序時都重新編譯它。


代碼演示

對於包,僅在單獨程序內的上下文中才有意義,下面做一個示例。本文下述指令,均在windows平臺下。

1 - 創建目錄

<code>md go_mod_demo/<code>

2 - 進入目錄,並創建包名

<code>go mod init demo.com/pkg/v1/<code>

執行後輸出如下

go: creating new go.mod: module demo.com/pkg/v1

這時,目錄下會多出一個 go.mod 文件,內容如下:

<code>module demo.com/pkg/v1
go 1.13/<code>

僅設置了包名,和go版本號。


3 - 創建一個包

首先,新建目錄

<code>md math/<code>

在該目錄下新建文件 math.go ,代碼如下

<code>package math

func Average(nums []float64) float64 {
\ttotal := float64(0)
\tfor _, x := range nums {
\t\ttotal += x
\t}
\treturn total / float64(len(nums))
}/<code>

聲明瞭表明為 math,並聲明瞭一個求64位浮點數數組的平均值的函數。


4 - 安裝math包

創建完之後,需要安裝這個包,提供外部調用。使用以下指令

<code>go install/<code>


5 - 創建主程序文件 main.go 並使用 math 包內函數

代碼如下:

<code>package main

import (
\t"fmt"

\t"demo.com/pkg/v1/math"
)


func main() {
\tnums := []float64{4.62, 90.31, 18.4, 70, 498}
\tavg := math.Average(nums)
\tfmt.Println(avg)
}/<code>

可以看到,我們導入包的名字為 “demo.com/pkg/v1/math” ,注意math是路徑名,而非包名。


6 - 檢查依賴關係並編譯

<code>go mod verify
go build -o pkg.exe/<code>

編譯完成後生成二進制文件 pkg.exe。執行該文件輸出內容如下:

<code>136.26600000000002/<code>


7 - 目錄樹

以上步驟我們就完成了這個小的示例,下圖是所有文件的目錄樹。


由淺入深:一個簡單的例子,讓你吃透Go語言自定義的包管理


深入瞭解編譯過程

對於上述的編譯過程,深入瞭解有助於我們理解go在包管理和連接上的運用次序。在編譯階段使用以下指令

<code>go build -x -o pkg.exe/<code>

會打印出所有編譯設計的步驟。我們逐一分析一下。

<code>WORK=C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\go-build011247454
mkdir -p $WORK\\b001\\/<code>

進入系統臨時目錄,並創建新的目錄用於操作。

<code>cat >$WORK\\b001\\importcfg.link << 'EOF' # internal
packagefile demo.com/pkg/v1=C:\\Users\\Administrator\\AppData\\Local\\go-build\\7d\\7dfb70c94793423aa270
96ae5d468f117ab2bdfd36637f56a335e015c7f422f2-d
packagefile demo.com/pkg/v1/math=C:\\Users\\Administrator\\AppData\\Local\\go-build\\9a\\9a761d7803a2508
d3bb14baf93c9bb63d690a2d2b96dcee9e2798266bf1a8c27-d
packagefile fmt=c:\\go\\pkg\\windows_amd64\\fmt.a
……(此處省去若干行)
packagefile internal/race=c:\\go\\pkg\\windows_amd64\\internal\\race.a
packagefile internal/syscall/windows/sysdll=c:\\go\\pkg\\windows_amd64\\internal\\syscall\\windows\\sysd
ll.a
packagefile internal/syscall/windows/registry=c:\\go\\pkg\\windows_amd64\\internal\\syscall\\windows\\re
gistry.a
EOF/<code>

這一步創建臨時連接文件 importcfg.link,並寫入內容。使用了為數較多的編譯後文件。

<code>mkdir -p $WORK\\b001\\exe\\
cd .
"c:\\\\go\\\\pkg\\\\tool\\\\windows_amd64\\\\link.exe" -o "C:\\\\Users\\\\ADMINI~1\\\\AppData\\\\Local\\\\Temp\\\\go-build011247454\\\\b001\\\\exe\\\\a.out.exe" -importcfg "C:\\\\Users\\\\ADMINI~1\\\\AppData\\\\Local\\\\Temp\\\\go-bui

ld011247454\\\\b001\\\\importcfg.link" -buildmode=exe -buildid=DI8V_Sm875LZ1CJe7Zp_/CjatiizQFDsD0wV9omHU/TXwkAnBjuzYJjfIEu300/DI8V_Sm875LZ1CJe7Zp_ -extld=gcc "C:\\\\Users\\\\Administrator\\\\AppData\\\\Local\\\\go-build\\\\7d\\\\7dfb70c94793423aa27096ae5d468f117ab2bdfd36637f56a335e015c7f422f2-d"
"c:\\\\go\\\\pkg\\\\tool\\\\windows_amd64\\\\buildid.exe" -w "C:\\\\Users\\\\ADMINI~1\\\\AppData\\\\Local\\\\Temp\\\\go-build011247454\\\\b001\\\\exe\\\\a.out.exe" # internal/<code>

這一步創建新目錄exe,並在該目錄下調用 link.exe 文件,使用上一步生成的 importcfg.link 內容。

之後調用 buildid.exe 文件編譯生成目標二進制文件 a.out.exe。

<code>cp $WORK\\b001\\exe\\a.out.exe pkg.exe
rm -r $WORK\\b001\\/<code>

這一步將生成的二進制文件重命名拷貝到目標目錄,並清空編譯臨時目錄。


結語

本文通過一個簡單的代碼示例,逐步編寫代碼,並將代碼編譯為二進制文件,涉及到了go在包管理和編譯過程中的方方面面。

“不積跬步無以至千里”,大的項目構建,結構複雜,功能繁多,更需要清楚go在包管理中的原理,可以避免走彎路。

Happy coding :-)


【本文由 發佈,持續分享編程與程序員成長相關的內容,歡迎關注】


分享到:


相關文章: