Go語(yǔ)言 基本技巧

2018-07-25 17:22 更新

研究Go的內(nèi)部實(shí)現(xiàn),這里介紹一些基本的技巧。

閱讀源代碼

Go語(yǔ)言的源代碼布局是有一些規(guī)律的。假定讀者在$GOROOT下:

- ./misc 一些工具
- ./src 源代碼
- ./src/cmd 命令工具,包括6c, 6l, 6g等等。最后打包成go命令。
- ./src/pkg 各個(gè)package的源代碼
- ./src/pkg/runtime Go的runtime包,本書分析的最主要的部分
-  AUTHORS — 文件,官方 Go語(yǔ)言作者列表
|– CONTRIBUTORS — 文件,第三方貢獻(xiàn)者列表
|– LICENSE — 文件,Go語(yǔ)言發(fā)布授權(quán)協(xié)議
|– PATENTS — 文件,專利
|– README — 文件,README文件,大家懂的。提一下,經(jīng)常有人說(shuō):Go官網(wǎng)打不開(kāi)啊,怎么辦?其實(shí),在README中說(shuō)到了這個(gè)。該文件還提到,如果通過(guò)二進(jìn)制安裝,需要設(shè)置GOROOT環(huán)境變量;如果你將Go放在了/usr/local/go中,則可以不設(shè)置該環(huán)境變量(Windows下是C:\go)。當(dāng)然,建議不管什么時(shí)候都設(shè)置GOROOT。另外,確保$GOROOT/bin在PATH目錄中。
|– VERSION — 文件,當(dāng)前Go版本
|– api — 目錄,包含所有API列表,方便IDE使用
|– doc — 目錄,Go語(yǔ)言的各種文檔,官網(wǎng)上有的,這里基本會(huì)有,這也就是為什么說(shuō)可以本地搭建”官網(wǎng)”。這里面有不少其他資源,比如gopher圖標(biāo)之類的。
|– favicon.ico — 文件,官網(wǎng)logo
|– include — 目錄,Go 基本工具依賴的庫(kù)的頭文件
|– lib — 目錄,文檔模板
|– misc — 目錄,其他的一些工具,相當(dāng)于大雜燴,大部分是各種編輯器的Go語(yǔ)言支持,還有cgo的例子等
|– robots.txt — 文件,搜索引擎robots文件
|– src — 目錄,Go語(yǔ)言源碼:基本工具(編譯器等)、標(biāo)準(zhǔn)庫(kù)
`– test — 目錄,包含很多測(cè)試程序(并非_test.go方式的單元測(cè)試,而是包含main包的測(cè)試),包括一些fixbug測(cè)試??梢酝ㄟ^(guò)這個(gè)學(xué)到一些特性的使用。

學(xué)習(xí)Go語(yǔ)言的內(nèi)部實(shí)現(xiàn),主要依靠對(duì)源代碼的分析,所以閱讀源代碼是很好的方式。linus談到如何學(xué)習(xí)Linux內(nèi)核時(shí)也說(shuō)過(guò)"Read the F**ing Source code"。

使用調(diào)試器

通過(guò)gdb下斷點(diǎn),跟蹤程序的行為。調(diào)試跟代碼的方式是源代碼閱讀的一種輔助手段。

用戶代碼入口是在main.main,runtime庫(kù)中的函數(shù)可以通過(guò)runtime.XXX斷點(diǎn)捕獲。比如寫一個(gè)test.go:

package main

import (
    "fmt"
)

func main() {
    fmt.Println("hello world!")
}

編譯,調(diào)試

go build test.go
gdb test

可以在main.main處下斷點(diǎn),單步執(zhí)行,你會(huì)發(fā)現(xiàn)進(jìn)入了一個(gè)runtime·convT2E的函數(shù)。這個(gè)就是由于fmt.Println接受的是一個(gè)interface,而傳入的是一個(gè)string,這里會(huì)做一個(gè)轉(zhuǎn)換。以這個(gè)為一個(gè)突破點(diǎn)去跟代碼,就可以研究Go語(yǔ)言中具體類型如何轉(zhuǎn)為interface抽象類型。

分析生成的匯編代碼

有時(shí)候分析會(huì)需要研究生成的匯編代碼,這里介紹生成匯編代碼的方法。

go tool 6g -S hello.go

-S參數(shù)表示打印出匯編代碼,更多參數(shù)可以通過(guò)-h參數(shù)查看。

go tool 6g -h

或者可以反匯編生成的可執(zhí)行文件:

go build test.go
go tool 6l -a test | less

本機(jī)是amd64的機(jī)器,如果是i386的機(jī)器,則命令是8g

需要注意的是用6g的-S生成的匯編代碼和6l -a生成的反匯編代碼是不太一樣的。前者是直接對(duì)源代碼進(jìn)行匯編,后者是對(duì)可執(zhí)行文件進(jìn)行反匯編。在6l進(jìn)行鏈接過(guò)程中,可能會(huì)在原匯編文件基礎(chǔ)上插入新的指令。所以6l反匯編出來(lái)的是最接近真實(shí)代碼的。

不過(guò)Go的匯編語(yǔ)法跟常用的有點(diǎn)不太一致,可能讀起來(lái)會(huì)不太習(xí)慣。還有另一種方式,就是在用gdb調(diào)試的過(guò)程中查看匯編。

gdb test
b main.main
disas

links


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)