天天看點

linux下go語言的test檔案夾,探究GO中各個目錄的功能

下載下傳Go源碼後,根目錄結構如下:

|– AUTHORS — 檔案,官方 Go語言作者清單

|– CONTRIBUTORS — 檔案,第三方貢獻者清單

|– LICENSE — 檔案,Go語言釋出授權協定

|– PATENTS — 檔案,專利

|— README — 檔案,README檔案,大家懂的。提一下,經常有人說:Go官網打不開啊,怎麼辦?其實,在README中說到了這個。該檔案還提到,如果通過二進制安裝,需要設定GOROOT環境變量;如果你将Go放在了/usr/local/go中,則可以不設定該環境變量(Windows下是C:\go)。當然,建議不管什麼時候都設定GOROOT。另外,確定$GOROOT/bin在PATH目錄中。

|– VERSION — 檔案,目前Go版本

|– api — 目錄,包含所有API清單,友善IDE使用

|– doc — 目錄,Go語言的各種文檔,官網上有的,這裡基本會有,這也就是為什麼說可以本地搭建”官網”。這裡面有不少其他資源,比如gopher圖示之類的。

|– favicon.ico — 檔案,官網logo

|– include — 目錄,Go 基本工具依賴的庫的頭檔案

|– lib — 目錄,文檔模闆

|– misc — 目錄,其他的一些工具,相當于大雜燴,大部分是各種編輯器的Go語言支援,還有cgo的例子等

|– robots.txt — 檔案,搜尋引擎robots檔案

|– src — 目錄,Go語言源碼:基本工具(編譯器等)、标準庫

`– test — 目錄,包含很多測試程式(并非_test.go方式的單元測試,而是包含main包的測試),包括一些fixbug測試。可以通過這個學到一些特性的使用。

下面詳細介紹一些目錄(可能分功能介紹)

一、api目錄

|– README

|– go1.txt

`– next.txt

通過閱讀README知道,go1.txt可以通過go tool api指令生成。而通過go1.txt可以做成編輯器的api自動提示,比如Vim:VimForGo

next.txt是一些将來可能加入的API

二、Go基本工具(cmd)

1、include目錄

該目錄包含以下檔案(檔案夾)

ar.h bio.h bootexec.h fmt.h libc.h mach.h plan9 u.h ureg_amd64.h ureg_arm.h ureg_x86.h utf.h

其中,plan9目錄是針對Plan 9作業系統的,從裡面的檔案名知道,跟include跟目錄下的是一個意思。

386 libc.h mach.h ureg_amd64.h ureg_arm.h ureg_x86.h (386目錄下就隻有一個u.h頭檔案)

1)u.h

根據Rob Pike在How to Use the Plan 9 C Compiler上的介紹以及檔案的源碼,知道u.h檔案定義了一些依賴架構(architecture-dependent)的類型(這樣使得該類型獨立于架構,不過依賴于編譯器),如用于setjmp系統調用的jmp_buf,以及類型int8、uint8等。

該檔案直接來源于plan9。位址:http://code.swtch.com/plan9port/src/tip/include/u.h。所有plan9 C程式必須在開始出包含該頭檔案(因為其他檔案引用了該檔案中的類型定義)

2)ureg.h

包括:ureg_amd64.h ureg_arm.h ureg_x86.h

該檔案定義了一個類型(struct):Ureg。定義了在系統棧上寄存器的布局

在ureg_x86.h中對各個字段有注釋:

struct Ureg

{

uint32 di;

uint32 si;

uint32 bp;

uint32 nsp;

uint32 bx;

uint32 dx;

uint32 cx;

uint32 ax;

uint32 gs;

uint32 fs;

uint32 es;

uint32 ds;

uint32 trap;

uint32 ecode;

uint32 pc;

uint32 cs;

uint32 flags;

union {

uint32 usp;

uint32 sp;

};

uint32 ss;

};

3)libc.h/utf.h/fmt.h

在嚴格的标準C中,頭檔案按相關功能分組在一個單獨檔案中:一個頭檔案用于字元串處理,一個頭檔案用于記憶體管理,一個頭檔案用于I/O處理,沒有頭檔案是用于系統調用的。plan9采用了不同的方式,一個C庫由strings函數、記憶體操作函數、一些格式化IO程式,加上所有和這些相關的系統調用。為了使用這些功能,需要包含libc.h頭檔案。該檔案從Inferno和Plan9中提取出來的。

該檔案開頭有幾行注釋:

在該檔案中包含了utf.h和fmt.h

在Plan 9中使用nil表示指針的零值,這也就是為什麼Go中采用nil了。nil的定義在libc.h中:

#ifndef nil

#define nil ((void*)0)

#endif

對于solaris,nil在u.h中有定義

另外,libc中聲明了很多系統調用

包含了該檔案之後,可以直接使用print、fprint之類的,而不需要包含标準IO庫,這是因為libc.h中包含了fmt.h,而fmt.h中提供了這些print函數。當然,如果需要使用printf,得導入stdio.h

utf.h是實際上引用了src/lib9/utf/utf.h,提供了對UNICODE字元集相關操作。

題外話:

Plan 9支援的每一種CPU架構都給其一個單個字母或數字的名稱:k表示SPARC,q表示Motorola Power PC 630和640,v表示MIPS,0表示little-endian MIPS,1表示Motorola 68000,2表示Motorola 68020和68040,5表示Acorn ARM 7500,6表示AMD64,7表示DEC Alpha,8表示Intel 386,9表示AMD 2900。可以看出,Go中5/6/8的由來了。

對于為什麼取這樣的名字,How to Use the Plan 9 C Compiler 中Heterogeneity有解釋。

注意:在看源碼過程中可能會看到

ARGBEGIN{

}ARGEND

這是在libc.h中定義的宏。這是一些處理指令行參數的宏。其他宏還有:

ARGF()

EARGF(x)

ARGC()

4)bio.h

上面提到,libc.h中包含了print等,這些IO是沒有buffer的。而bio.h提供了buffer I/O,這是推薦使用的方式。這個和ANSI标準I/O,stdio.h類似。

根據官方說法,Bio更小、更高效,特别是buffer-at-a-time或line-at-a-time I/O,即使character-at-a-time I/O也比stdio更快。

和其他系統明顯不同的是,Plan 9中I/O的接口的文本不是ASCII編碼,而是UTF(ISO叫做UTF-8)編碼。一個字元在Plan 9中稱為rune,也叫做Code-point。(Go中沿用了該叫法)

看一下utf.h中的一個枚舉類型

{

UTFmax = 4,

Runesync = 0x80,

Runemax = 0x10FFFF,

};

引用一段解釋:

The library defines several symbols relevant to the representation of characters. Any byte with unsigned value less than Runesync will not appear in any multi-byte encoding of a character. Utfrune compares the character being searched against Runesync to see if it is sufficient to call strchr or if the byte stream must be interpreted. Any byte with unsigned value less than Runeself is represented by a single byte with the same value. Finally, when errors are encountered converting to runes from a byte stream, the library returns the rune value Runeerror and advances a single byte. This permits programs to find runes embedded in binary data.

關于UTF8的操作在utf.h檔案中聲明了

5)ar.h

iar是一個壓縮指令,該壓縮的檔案格式通過ar.h頭檔案描述。

6)bootexec.h/mach.h

該檔案定義了一些架構私有的引導執行程式的檔案頭格式(引導程式)。這是Plan 9(Inferno的祖先)作業系統的說明:The header format of a bootable executable is defined by each manufacturer. Header file /sys/include/bootexec.h contains structures describing the headers currently supported.

該檔案定義了一些特定架構的應用程式資料。目前支援的架構:

該檔案中列出了詳細的支援的架構類型(可執行檔案)

bootexec.h是針對引導程式的;mach.h是針對應用程式的。

2、src下的lib9/libbio/libmach

由include目錄中檔案的名字知道,這三個目錄分别是libc.h、bio.h和mach.h三個頭檔案的實作。具體代碼有興趣可以看看。

這些都是Plan 9或Inferno作業系統的庫

3、src/cmd 包含了各種工具的源碼

目錄如下:

5a 5c 5g 5l 6a 6c 6g 6l 8a 8c 8g 8l addr2line api cc cgo dist fix gc go godoc gofmt ld nm objdump pack vet yacc

一個目錄對應一個工具

除了go/godoc/gofmt/dist,其他工具的使用方式:

go tool 工具名 xxx

經過前面的介紹,看到這些名字,應該大概猜到是啥了。

我們看一下Plan 9中檔案字尾的問題

前面我們知道,AMD64上,标示是6,我們以這個為例。

根據Plan 9命名規則,AMD64上的C編譯器是6c,彙編器是6a,連結器或裝載器是6l。c檔案編譯後生成的對象檔案字尾是.6,連結後預設的可執行檔案名是6.out。

5/6/8這一序列中,跟Plan 9是一緻的,另外,新增了一個g,表示Go編譯器。通過這些工具編譯Go檔案生成的中間檔案對象的字尾和C檔案編譯後是一樣的,以.5/6/8結尾。

說到這裡提醒一下,目前Go編譯不建議直接通過5g/6g/8g這樣的進行,而是使用go這個工具(網上很多Go1正式版釋出之前的文章用的是6g這樣的工具)

5/6/8這一序列中,每個目錄下的都有一個doc.go檔案,這個檔案大概說明了該工具的作用。這一序列工具具體的源碼,感興趣的可以閱讀。

1)cc/gc/ld分别是C編譯器、Go編譯器和連結器

這三個可以看成是對5/6/8序列的抽象(不依賴具體架構)

2)api 可以生産所有Go包的API清單。

GOROOT/api中的go1.txt就可以通過這個工具生産

3)cgo 允許通過調用C代碼建立Go包

4)fix 找到用舊API寫的Go程式,然後用新API重寫他們。

這個可用于Go更新了,處理用之前版本Go寫的應用程式。

5)go 管理Go源代碼的工具,很好用很重要的一個工具。

應該總是使用go這個工具,而不是使用6g這樣的工具。當然,如果需要生産中間對象,可以使用6g這樣的工具。

6)godoc 提取并生産Go程式文檔(包括Go本身)

7)gofmt 格式化Go程式代碼

8)nm 是Plan 9中的nm工具

。詳細說明:http://plan9.bell-labs.com/magic/man2html/1/nm 。檢視符号表用的

9)pack 是Plan 9中的ar工具,這個用來歸檔目标檔案。

pkg中的.a檔案就是pack生成的。詳細說明:http://plan9.bell-labs.com/magic/man2html/1/ar

10)vet 用于檢查并報告Go源碼中可疑的結構。

比如調用Printf,它的參數和格式化字元串提供的不一緻,如:fmt.Printf(“%s is %s”, name),這樣會被檢查出來。

11)yacc Go版本的yacc。

http://plan9.bell-labs.com/magic/man2html/1/yacc。這是一個經典的生成文法分析器的工具。更多詳細說明,可以查閱相關資料。Yacc 與 Lex 快速入門

以上工具目錄中都有doc.go檔案,用于生成文檔。http://golang.org/cmd/可以檢視。

12)addr2line linux下有這個指令。

這是一個addr2line的模拟器,隻是為了使pprof能夠在mac上工作。關于addr2line,可以檢視linux的man手冊,也可以看addr2line探秘

13)objdump linux下有這個指令。

這是一個objdump的模拟器,隻是為了使pprof能夠在mac上工作。關于objdump,可以檢視linux的man手冊

14)dist 這是一個重要的工具。它是一個引導程式,負責建構Go其他基本工具。通過源碼安裝Go時,會先安裝該工具。

注:安裝完之後,pkg/tool/$GOOS_$GOARCH下面的pprof工具是從misc下面copy過來的

四、安裝腳本

通過源碼安裝Go相當簡單(安裝速度也很快),因為它提供了友善的腳本。腳本在src目錄下

all.bash/all.bat — 會執行make腳本和run腳本

make.bash/make.bat — 安裝Go

run.bash/run.bat — 測試标準庫

是以,通過源碼安裝Go,一般cd到src目錄執行./all.bash。如果不想測試标準庫,可以直接./make.bash,這樣會比較快。

Make.dist 被其他Makefile檔案引用,比如cmd下面的很多工具中的Makefile檔案。這個檔案的作用是:運作go tool dist去安裝指令,同時在安裝過程中會列印出執行了該檔案的目錄名。可見,在源碼安裝Go的過程中,列印出的大部分資訊就是這個檔案的作用。

五、src/pkg Go标準庫源碼