go——工程结构
Go是一門推崇軟件工程理念的編程語言,它為開發(fā)周期的每個(gè)環(huán)節(jié)都提供了完備的工具和支持。
Go語言高度強(qiáng)調(diào)代碼和項(xiàng)目的規(guī)范和統(tǒng)一,這幾種體現(xiàn)在工程結(jié)構(gòu)或者說代碼體制的細(xì)節(jié)之處。
1.工作區(qū)
一般情況下,Go源碼文件必須放在工作區(qū)中。但是對(duì)于命令源碼文件來說,這不是必須的。
工作區(qū)其實(shí)就是一個(gè)對(duì)應(yīng)于特定工程的目錄,它應(yīng)該包含3個(gè)子目錄:src目錄、pkg目錄和bin目錄。
(1)src目錄
用于以代碼包的形式組織并保存Go源碼文件,這里的代碼包與src下的子目錄一一對(duì)應(yīng)。
例如,若一個(gè)源碼文件被聲明屬于代碼包log,那么它就應(yīng)該保存在src/log目錄下。
當(dāng)然,你也可以直接把Go源碼文件直接放在src目錄下,但這樣的Go源碼文件就只能被聲明屬于main代碼包。
除非用于臨時(shí)測(cè)試或演示,一般還是建議把Go源碼文件放入特定的代碼包中。
(2)pkg目錄
用于存放通過go install命令安裝后的代碼包的歸檔文件。
前提是代碼包中必須包含Go庫源碼文件。歸檔文件是指那些名稱以“.a”結(jié)尾的文件。
該目錄與GOROOT目錄下的pkg目錄功能類似。
區(qū)別在于,工作區(qū)中的pkg目錄專門用來存放用戶代碼的歸檔文件。
編譯和安裝用戶代碼的過程一般會(huì)以代碼包為單位進(jìn)行。
比如log包被編譯安裝后,將生成一個(gè)名為log.a的歸檔文件,并存放在當(dāng)前工作區(qū)的pkg目錄下的平臺(tái)相關(guān)目錄中。
(3)bin目錄
與pkg目錄類似,在通過go install命令完成安裝后,保存由Go命令源碼文件生成的可執(zhí)行文件。
(其實(shí)上面文字的意思就是什么類型的文件放在什么目錄下面,盡量規(guī)劃好工作區(qū))
命令源碼文件:就是聲明屬于main代碼包并包含無參聲明和結(jié)果聲明的main函數(shù)的源碼文件。
這類源碼文件就是程序的入口,它們可以獨(dú)立運(yùn)行(使用go run命令),
也可以通過go build或go install命令得到相應(yīng)的可執(zhí)行文件。
庫源碼文件:是指存在于某個(gè)代碼包中普通源碼文件。
?
2.源碼文件
(1)命令源碼文件
如果一個(gè)源碼文件被聲明屬于main代碼包,且該文件代碼中包含無參數(shù)聲明和結(jié)果聲明的main函數(shù),則它就是命令源碼文件。
命令源碼文件可以直接通過go run命令直接啟動(dòng)運(yùn)行。
同一個(gè)代碼中的所有的源碼文件,其所屬代碼包的名稱必須一致。
如果命令源碼文件和庫源碼文件處于同一個(gè)代碼包中,那么在該包中就無法正確執(zhí)行g(shù)o build和go install命令。
換句話說,這些源碼文件將無法通過常規(guī)方法編譯和安裝。
因此,命令源碼文件通常會(huì)單獨(dú)放在一個(gè)代碼包中,因?yàn)橥ǔR粋€(gè)程序模塊或軟件的啟動(dòng)入口只有一個(gè)。
同一個(gè)代碼包中可以有多個(gè)命令源碼文件,可通過go run命令分別運(yùn)行,但這會(huì)使go build和go install命令無法編譯和安裝該代碼包。
當(dāng)代碼包中有且只有一個(gè)命令源碼文件時(shí),在文件所在目錄中執(zhí)行g(shù)o build命令,
則可在該目錄下生成一個(gè)與目錄同名的可執(zhí)行文件;
? 若使用go install命令,則可在當(dāng)前工作區(qū)的bin目錄下生成相應(yīng)的可執(zhí)行文件。
需要注意的是,只有當(dāng)前環(huán)境變量GOPATH中只包含一個(gè)工作區(qū)的目錄路徑時(shí),
go install命令才會(huì)把命令源碼文件安裝到當(dāng)前工作區(qū)的bin目錄下;
?
(2)庫源碼文件
通常,庫源碼文件聲明的包名會(huì)與它直接所屬的代碼包一致,且?guī)煸创a文件中不包含無參數(shù)聲明和無結(jié)果聲明的main函數(shù)。
通過執(zhí)行g(shù)o install命令,成功安裝了該包并生成了若干歸檔文件。
由于我們指定了工作區(qū)GOPATH的路徑是/root/example.v2,則會(huì)在這個(gè)目錄下生成bin和pkg文件。
run install之前:
? run install之后:
?
?
(3)測(cè)試源碼文件
測(cè)試源碼文件是一種特殊的庫文件,可以通過執(zhí)行g(shù)o test命令運(yùn)行當(dāng)前代碼包下的所有測(cè)試源碼文件。
成為測(cè)試源碼文件的充分條件有兩個(gè):
A.文件名需要以"_test.go"結(jié)尾
B.文件中需要至少包含一個(gè)名稱以Test開頭或Benchmark開頭,且擁有一個(gè)類型為*testing.T或*testing.B的參數(shù)的函數(shù)。
*testing.T或*testing.B是兩個(gè)結(jié)構(gòu)體類型。而*testing.T或*testing.B則分別為前兩者的指針類型。它們分別是功能測(cè)試和基準(zhǔn)測(cè)試所需。
? 當(dāng)在一個(gè)代碼包中之心go test命令時(shí),該代碼包中的所有測(cè)試源碼文件會(huì)被找到并運(yùn)行。
?
3.代碼包
在Go中,代碼包是代碼編譯和安裝的基本單元,也是非常直觀的代碼組織形式。
(1)包聲明
在Go語言中,代碼包中的源碼文件可以任意命令。
但是,這些任意名稱的源碼文件都必須以包聲明語句作為文件代碼中的第一行。
例如,example.v2/src/gopcp.v2/helper/log/base包中的所有源碼文件都先聲明自己屬于某一個(gè)代碼包:
? 分別打印第一行:
? 其中,package是Go中用于包聲明語句的關(guān)鍵字。
Go規(guī)定包聲明中的包名是代碼路徑的最后一個(gè)元素。
? 所以包名是base。
但是,不論命令源文件存放在哪個(gè)代碼包中,它都必須聲明屬于main包。
(2)包導(dǎo)入
代碼包gopcp.v2/helper/log中的logger.go需要依賴base子包和logrus子包,
因此需要在源碼文件中使用代碼包導(dǎo)入語句,如:
全路徑是:/root/example.v2/src/gopcp.v2/helper/log,但是所有的源代碼都在src下面,所以這里使用相對(duì)路徑。
當(dāng)導(dǎo)入多個(gè)代碼包時(shí),你需要用圓括號(hào),每個(gè)代碼包名占一行。
同一個(gè)源碼文件中導(dǎo)入多個(gè)代碼包的最后一個(gè)元素不能重復(fù),否則一旦使用其中的程序?qū)嶓w,就會(huì)引起編譯錯(cuò)誤。
但是,如果你只導(dǎo)入不適用,同樣會(huì)引起編譯錯(cuò)誤,一個(gè)解決辦法就是為其中一個(gè)起別名。
如果我們想不加前綴而直接使用某個(gè)依賴包中的程序?qū)嶓w,就可以用"."來代替別名。
import ( . "gopcp.v2/helper/log/logrus" )所以我們就可以這樣引用:
var logger = NewLogger("gopcp") //NewLogger是logrus中的一個(gè)函數(shù)。我們可以看到,因?yàn)?#34;."的緣故,可以直接引用包中的函數(shù),而不需要指定路徑。
在Go中,變量、常量、函數(shù)和類型聲明可統(tǒng)稱為程序?qū)嶓w,而它們的名稱統(tǒng)稱為標(biāo)識(shí)符。
標(biāo)識(shí)符可以是Unicode字符集中任意能表示自然語言文字的字符、數(shù)字以及下劃線(_)。標(biāo)識(shí)符不能以數(shù)字或下劃線開頭。
實(shí)際上,標(biāo)識(shí)符的首字符的大小寫控制著對(duì)應(yīng)程序?qū)嶓w的訪問權(quán)限。
如果標(biāo)識(shí)符的首字符是大寫形式,那么它所對(duì)應(yīng)的程序?qū)嶓w就可以被本代碼之外的代碼訪問到,也稱之為可導(dǎo)出或公開的;
否則,對(duì)應(yīng)的程序?qū)嶓w就只能被本包內(nèi)的代碼訪問,也成為不可導(dǎo)出的或包私有的。
要想成為可導(dǎo)出的程序?qū)嶓w,還需要額外滿足以下兩個(gè)條件。
程序?qū)嶓w必須是非局部的。局部的程序?qū)嶓w是指:它被定義在了函數(shù)或結(jié)構(gòu)體的內(nèi)部。
代碼包所屬目錄必須包含在GOPATH中定義的工作區(qū)目錄中。
代碼包導(dǎo)入還有另一種情況:如果只想初始化某個(gè)代碼包,
而不需要在當(dāng)前源碼文件中使用那個(gè)代碼包中的任何程序?qū)嶓w,就可以用“_”來代替別名。
這種情況下,我們只是觸發(fā)了這個(gè)代碼包的初始化操作,符號(hào)"_"就像一個(gè)垃圾桶。
(3)包初始化
在Go中,可以有專門的函數(shù)負(fù)責(zé)代碼包初始化,成為代碼包初始化函數(shù)。
這個(gè)函數(shù)無任何參數(shù)聲明和結(jié)果聲明,且名稱必須為init。
Go會(huì)在程序真正執(zhí)行前對(duì)整個(gè)程序的依賴進(jìn)行分析,并初始化相關(guān)的代碼包。
也就是說,所有的代碼包初始化函數(shù)都會(huì)在main函數(shù)(命令源碼文件的入口函數(shù))執(zhí)行前執(zhí)行完畢,而且只會(huì)執(zhí)行一次。
另外,對(duì)于每一個(gè)代碼包來說,其中的所有全局變量的初始化,都會(huì)在代碼包的初始化函數(shù)執(zhí)行前完成。
這避免了在代碼包初始化函數(shù)對(duì)某個(gè)變量進(jìn)行賦值之后,又被該變量聲明中賦予的值覆蓋掉的問題
下面是一個(gè)簡單示例:
?
轉(zhuǎn)載于:https://www.cnblogs.com/yangmingxianshen/p/10089615.html
總結(jié)
- 上一篇: 2018.12.08 codeforce
- 下一篇: jmeter参数化之用户参数