400块钱3小时上门服务,同城附近人100米,怎么找同城的人服务,夜场女都是为了钱吗

    <strike id="t98gp"></strike>

    1. <code id="t98gp"></code>

      <nav id="t98gp"></nav>
    2. <object id="t98gp"></object>
      首頁 Golang教程Go:符號表是什么?如何使用?

      Go:符號表是什么?如何使用?

      運維派隸屬馬哥教育旗下專業運維社區,是國內成立最早的IT運維技術社區,歡迎關注公眾號:yunweipai
      領取學習更多免費Linux云計算、Python、Docker、K8s教程關注公眾號:馬哥linux運維

      ?? 本文基于 Go 1.13 ,原文及譯者信息在文末。

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

      符號表

      Go 編譯的所有二進制文件默認內嵌了符號表。我們來舉一個例子并研究它。下面是代碼:

      var AppVersion string

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

      可以通過命令 nm 來展示符號表;下面是從 OSX 的結果中提取的部分信息:

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

      用 b(全稱為 bss)標記的符號是未初始化的數據。由于我們前面的變量 AppVersion 沒有初始化,因此它屬于 b。符號 d 表示已初始化的數據,t 表示文本符號, 函數屬于其中之一。

      Go 也封裝了 nm 命令,可以用命令 go tool nm 來使用它,也能生成相同的結果:

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

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

      自定義變量

      當執行命令 go build 時,經過了兩個階段:編譯和構建。構建階段通過編譯過程中生成的對象文件生成了一個可執行文件。為了實現這個階段,構建器把符號表中的符號重定向到最終的二進制文件。

      在 Go 中我們可以用 -X 來重寫一個符號定義,-X 兩個入參:名稱和值。下面是承接前面的代碼的例子:

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

      構建并運行程序,現在會展示在命令行中定義的版本:

      Version: v1.0.0

      運行 nm 命令會看到變量已被初始化:

      1170a90 D main.AppVersion

      投建器賦予了我們重寫數據符號(類型 b 或 d)的能力,現在它們有了 Go 中的 string 類型。下面是那些符號列表:

      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,它們都是被構建器自動設置的。我們來看一下運行時這些符號的意義。

      調試

      符號表的存在是為了確保標識符在使用之前已被聲明。這意味著當程序被構建后,它就不再需要這個表了。然而,默認情況下符號表是被嵌入到了 Go 的二進制文件以便調試。我們先來理解如何利用它,之后再來看怎么把它從二進制文件中刪除。

      我會用 gdb 來調試。只需要執行 gdb ex 就可以加載二進制文件?,F在程序已被加載,我們用 list 命令來展示源碼。下面是輸出:

      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 初始化的第一步是讀取符號表,為了提取程序中函數和符號的信息。我們現在可以用 -ldflags=-s 參數不把符號表編譯進程序。下面是新的輸出:

      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.

      現在調試器由于找不到符號表不能展示源碼。我們應該留意到使用 -s 參數去掉了符號表的同時,也去掉了對調試器很有用的 [DWARF](https://golang.org/pkg/debug/dwarf/ "DWARF") 調試信息。

      二進制文件的大小

      去掉符號表后會讓調試器用起來很困難,但是會減少二進制文件的大小。下面是有無符號表的二進制文件的區別:

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

      沒有符號表比有符號表會小 25%。下面是編譯 cmd/go 源碼的另一個例子:

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

      這里沒有符號表和 DWARF 信息,也小了 25%。

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

      作者:Vincent Blanchon 譯者:lxbwolf  校對:polaris1119

      本文由 GCTT  原創編譯,Go 中文網 榮譽推出

      本文鏈接:http://www.605748.com/42740.html

      網友評論comments

      發表評論

      您的電子郵箱地址不會被公開。

      暫無評論

      Copyright ? 2012-2022 YUNWEIPAI.COM - 運維派 京ICP備16064699號-6
      掃二維碼
      掃二維碼
      返回頂部
      400块钱3小时上门服务,同城附近人100米,怎么找同城的人服务,夜场女都是为了钱吗