1. 程式人生 > >Go包-程式碼組織者

Go包-程式碼組織者

前言

在上一節(聊聊Go的工作空間),提到了Go包,這一節,我們就來仔細講講。

什麼是Go包

Go語言中的包,其實是一種組織程式碼的方式。Go 的程式都會組織成若干組檔案,而每組檔案被稱為一個包。go安裝完成之後,在GOROOT/src目錄,自帶了各種各樣的包,例如常用的io包、fmt包、math包等。我們就來分析下io包,看看go內建的包是如何組織程式碼的。
tree io包
上圖顯示的就是io包的目錄結構,分別開啟io.gomulti.gopipe.go,你會發現在檔案非註釋的第一行都聲明瞭package io。沒錯,這三個原始檔都屬於同一個go包–io包。到這裡,其實已經很明白了,所謂的go包就是計算機中的目錄,通俗點講就是檔名。go語言就是這樣通過它們進行目錄結構和檔案組織的。在io

包目錄下,其實還有個ioutil包,感興趣的同學可以開啟ioutil目錄下的檔案,一探究竟。(以_test.go結尾的測試檔案,忽略)

包應該如何命名

使用關鍵字–package和go檔案所在目錄同名,這是go包命名的最大原則,其次還應該做到簡潔清晰全小寫。這種命名方式有利於開發時書寫包名,查詢和定位。例如,上面提到的 io包、ioutil包,命名都很簡短且清晰。所屬io包的三個檔案,在檔案開頭都聲明瞭package io

包的匯入

使用關鍵字–import。使用一個包,必須先將包匯入(不管是go內建包還是自己寫的包)。例如:

// 匯入單個包
import "fmt"
// 使用go語言提供的匯入快,匯入多個包,每個包獨佔一行
import (
	"fmt"
	"io/ioutil"
	"github.com/Seekload/stringutil"
)

import告訴編譯器到磁碟的哪裡去找想要匯入的包。其實,上面匯入fmtio/ioutilgithub.com/Seekload/stringutil是一個相對路徑,編譯器會使用 Go 環境變數(GOROOTGOPATH)設定的路徑,通過引入的相對路徑來查詢磁碟上的包。例如io/ioutil,編譯器最終會在GOROOT/src/io/ioutil路徑下查詢到ioutil包。類似的,會在GOPATH/src/github.com/Seekload/stringutil

路徑下查詢到stringutil包。提一點:編譯器在查詢的時候,會優先在GOROOT路徑下查詢,其次,在GOPATH下查詢,查詢無果之後會報編譯錯誤。
匯入包完成之後,就可以使用包提供的常量、函式等,例如:

fmt.Println();
ioutil.ReadDir();

獲取遠端包

某一天,你在瀏覽github,發現一個函式豐富的包,想在自己的專案上使用,目前,你想到的引用辦法可能就是直接將包clone到本地,然後放到GOPATH/src/目錄,開始引用。其實,有一種更簡便的方式,就是遠端匯入–使用go get命令。這種匯入的前提就是,包託管在一個分散式的版本控制系統上,比如Github等,並且是Public的許可權。
我在GitHub上就有一個github.com/Seekload/stringutil包(使用自己的域名作為包名一部分是為了避免包名重複,GitHub上的包太多了~),大家可以跟著我實操一下:
大家看下,我的工作空間目前是這樣的,
在這裡插入圖片描述
GOPATH執行go get github.com/Seekload/stringutil匯入遠端包之後:
go get
可以看到stringutil包已經下載到工作空間,並且已經生成靜態庫檔案stringutil.a,說明對包已進行過編譯和安裝。注意go get工具可以遞迴獲取依賴包,如果github.com/Seekload/stringutil也引用了其他的遠端包,也可以一併下載下來。
好了,現在就可以在hello.go中匯入包了

package main

import (
	"fmt"
	"github.com/Seekload/stringutil"
)

func main() {
	fmt.Println(stringutil.Reverse("!oG ,daolkeeS"))
}

執行編譯安裝go install hello/,生成可執行檔案hello
在這裡插入圖片描述

命名匯入

import支援多個包匯入,如果匯入的包出現重名,該怎麼辦?別擔心,Go開發團隊已經考慮到這個問題了,提供給我們的方法就是,對匯入的包重新命名–即命名匯入:在 import 語句給出的包路徑的左側定義一個名字,將匯入的包命名為新名字。看程式碼:

package main

import (
	"fmt"
	myfmt "github.com/Seekload/stringutil/fmt"
)

func main() {
	fmt.Println()
	myfmt.Println()
}

如果,程式碼裡匯入了一個沒有用到的包,Go編譯器不會告警,而是直接編譯失敗,並丟擲一個錯誤。Go 開發團隊認為,匯入的包應該被使用。不然,無用的包過多,會使程式碼變得臃腫且管理繁瑣。不過,有時,我們需要匯入一個包,但是又用不到,怎麼辦?沒關係,Go提供了空白識別符號 _ 來重新命名這個包匯入。

package main

import (
	"fmt"
	_ "github.com/Seekload/stringutil/fmt"
)

這裡提到了下劃線字元_,以後還會接觸到。

下劃線字元 _ 稱為空白識別符號,作用:拋棄不想繼續使用的值,如給匯入的包賦予一個空名字,或者忽略函式返回的你不感興趣的值。

關於Go包就講解到這裡,歡迎大家掃碼關注公眾號,敬請期待更多精彩文章!