久久国产乱子伦精品免费M,亚洲一区二区三区91,欧美国产在线视频,国产精品视频久久

詳述 Golang 的符號(hào)表

???本文基于 Go 1.13。

符號(hào)表是由編譯器生成和維護(hù)的,保存了與程序相關(guān)的信息,如函數(shù)和全局變量。理解符號(hào)表能幫助我們更好地與之交互和利用它。

符號(hào)表

Go 編譯的所有二進(jìn)制文件默認(rèn)內(nèi)嵌了符號(hào)表。我們來(lái)舉一個(gè)例子并研究它。下面是代碼:

var?AppVersion?string

func?main()?{
?fmt.Println(`Version:?`+AppVersion)
}

可以通過(guò)命令?nm?來(lái)展示符號(hào)表;下面是從?OSX?的結(jié)果中提取的部分信息:

0000000001177220?b?io.ErrUnexpectedEOF
[...]
0000000001177250?b?main.AppVersion
00000000010994c0?t?main.main
[...]
0000000001170b00?d?runtime.buildVersion

用?b(全稱(chēng)為?bss)標(biāo)記的符號(hào)是未初始化的數(shù)據(jù)。由于我們前面的變量?AppVersion?沒(méi)有初始化,因此它屬于?b。符號(hào)?d?表示已初始化的數(shù)據(jù),t?表示文本符號(hào), 函數(shù)屬于其中之一。

Go 也封裝了?nm?命令,可以用命令?go tool nm?來(lái)使用它,也能生成相同的結(jié)果:

1177220?B?io.ErrUnexpectedEOF
[...]
1177250?B?main.AppVersion
10994c0?T?main.main
[...]
1170b00?D?runtime.buildVersion

當(dāng)我們知道了暴露的變量的名字后,我們就可以與之交互。

自定義變量

當(dāng)執(zhí)行命令?go build?時(shí),經(jīng)過(guò)了兩個(gè)階段:編譯和構(gòu)建。構(gòu)建階段通過(guò)編譯過(guò)程中生成的對(duì)象文件生成了一個(gè)可執(zhí)行文件。為了實(shí)現(xiàn)這個(gè)階段,構(gòu)建器把符號(hào)表中的符號(hào)重定向到最終的二進(jìn)制文件。

在 Go 中我們可以用?-X?來(lái)重寫(xiě)一個(gè)符號(hào)定義,-X?兩個(gè)入?yún)ⅲ好Q(chēng)和值。下面是承接前面的代碼的例子:

go?build?-o?ex?-ldflags="-X?main.AppVersion=v1.0.0"

構(gòu)建并運(yùn)行程序,現(xiàn)在會(huì)展示在命令行中定義的版本:

Version:?v1.0.0

運(yùn)行?nm?命令會(huì)看到變量已被初始化:

1170a90?D?main.AppVersion

投建器賦予了我們重寫(xiě)數(shù)據(jù)符號(hào)(類(lèi)型?b?或?d)的能力,現(xiàn)在它們有了 Go 中的?string?類(lèi)型。下面是那些符號(hào)列表:

D?runtime.badsystemstackMsg
D?runtime.badmorestackgsignalMsg
D?runtime.badmorestackg0Msg
B?os.executablePath
B?os.initCwd
B?syscall.freebsdConfArch
D?runtime/internal/sys.DefaultGoroot
B?runtime.modinfo
B?main.AppVersion
D?runtime.buildVersion

在列表中我們看到了之前的變量和?DefaultGoroot,它們都是被構(gòu)建器自動(dòng)設(shè)置的。我們來(lái)看一下運(yùn)行時(shí)這些符號(hào)的意義。

調(diào)試

符號(hào)表的存在是為了確保標(biāo)識(shí)符在使用之前已被聲明。這意味著當(dāng)程序被構(gòu)建后,它就不再需要這個(gè)表了。然而,默認(rèn)情況下符號(hào)表是被嵌入到了 Go 的二進(jìn)制文件以便調(diào)試。我們先來(lái)理解如何利用它,之后再來(lái)看怎么把它從二進(jìn)制文件中刪除。

我會(huì)用?gdb?來(lái)調(diào)試。只需要執(zhí)行?gdb ex?就可以加載二進(jìn)制文件?,F(xiàn)在程序已被加載,我們用?list?命令來(lái)展示源碼。下面是輸出:

GNU?gdb?(GDB)?8.3.1
[...]
Reading?symbols?from?ex...
Loading?Go?Runtime?support.
(gdb)?list?10
6
7??var?AppVersion?string
8
9??func?main()?{
10????fmt.Println(`Version:?`+AppVersion)
11?}
12
(gdb)

gdb?初始化的第一步是讀取符號(hào)表,為了提取程序中函數(shù)和符號(hào)的信息。我們現(xiàn)在可以用?-ldflags=-s?參數(shù)不把符號(hào)表編譯進(jìn)程序。下面是新的輸出:

GNU?gdb?(GDB)?8.3.1
[...]
Reading?symbols?from?ex...
(No?debugging?symbols?found?in?ex)
(gdb)?list
No?symbol?table?is?loaded.??Use?the?"file"?command.

現(xiàn)在調(diào)試器由于找不到符號(hào)表不能展示源碼。我們應(yīng)該留意到使用?-s?參數(shù)去掉了符號(hào)表的同時(shí),也去掉了對(duì)調(diào)試器很有用的?[DWARF](https://golang.org/pkg/debug/dwarf/ "DWARF")?調(diào)試信息。

二進(jìn)制文件的大小

去掉符號(hào)表后會(huì)讓調(diào)試器用起來(lái)很困難,但是會(huì)減少二進(jìn)制文件的大小。下面是有無(wú)符號(hào)表的二進(jìn)制文件的區(qū)別:

2,0M??7?f?é?v?15:59?ex
1,5M??7?f?é?v?15:22?ex-s

沒(méi)有符號(hào)表比有符號(hào)表會(huì)小 25%。下面是編譯?cmd/go?源碼的另一個(gè)例子:

14M??7?f?é?v?16:58?go
11M??7?f?é?v?16:58?go-s

這里沒(méi)有符號(hào)表和 DWARF 信息,也小了 25%。

如果你想了解為什么二進(jìn)制文件會(huì)變小,我推薦你閱讀 WebKit 團(tuán)隊(duì)的?Benjamin Poulain的文章“不尋常的加速:二進(jìn)制文件大小”。

鏈接:https://medium.com/a-journey-with-go/go-how-to-take-advantage-of-the-symbols-table-360dd52269e5

(版權(quán)歸原作者所有,侵刪)

相關(guān)新聞

歷經(jīng)多年發(fā)展,已成為國(guó)內(nèi)好評(píng)如潮的Linux云計(jì)算運(yùn)維、SRE、Devops、網(wǎng)絡(luò)安全、云原生、Go、Python開(kāi)發(fā)專(zhuān)業(yè)人才培訓(xùn)機(jī)構(gòu)!

    1. 主站蜘蛛池模板: 崇左市| 临城县| 麟游县| 陆丰市| 高平市| 闽侯县| 胶州市| 天门市| 赣州市| 滦平县| 昭平县| 仙居县| 桃园县| 简阳市| 通河县| 陆川县| 濮阳市| 翼城县| 县级市| 行唐县| 绍兴县| 竹溪县| 江北区| 宣威市| 昌黎县| 大连市| 巴里| 锡林浩特市| 区。| 东乡族自治县| 托里县| 榕江县| 兰溪市| 台中县| 赫章县| 灵武市| 麦盖提县| 大港区| 密山市| 呼和浩特市| 临沂市|