<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          贈(zèng)書福利 | 為什么要了解 Go 語言編譯器?

          共 5368字,需瀏覽 11分鐘

           ·

          2021-10-22 08:55

          大家好,我是米開朗基楊。

          編譯器是一個(gè)大型且復(fù)雜的系統(tǒng),一個(gè)好的編譯器會(huì)很好地結(jié)合形式語言理論、算法、人工智能、系統(tǒng)設(shè)計(jì)、計(jì)算機(jī)體系結(jié)構(gòu)及編程語言理論。Go語言的編譯器遵循了主流編譯器采用的經(jīng)典策略及相似的處理流程和優(yōu)化規(guī)則(例如經(jīng)典的遞歸下降的語法解析、抽象語法樹的構(gòu)建)。另外,Go語言編譯器有一些特殊的設(shè)計(jì),例如內(nèi)存的逃逸等。

          編譯原理值得用一本書的筆墨去講解,通過了解Go語言編輯器,不僅可以了解大部分高級(jí)語言編譯器的一般性流程與規(guī)則,也能指導(dǎo)我們寫出更加優(yōu)秀的程序。很多Go語言的語法特性都離不開編譯時(shí)與運(yùn)行時(shí)的共同作用。另外,如果讀者希望開發(fā)go import、go fmt、go lint等掃描源代碼的工具,那么同樣離不開編譯器的知識(shí)和Go語言提供的API。

          Go語言編譯器的階段

          如圖1-1所示,在經(jīng)典的編譯原理中,一般將編譯器分為編譯器前端、優(yōu)化器和編譯器后端。這種編譯器被稱為三階段編譯器(three-phase compiler)。其中,編譯器前端主要專注于理解源程序、掃描解析源程序并進(jìn)行精準(zhǔn)的語義表達(dá)。編譯器的中間階段(Intermediate Representation,IR)可能有多個(gè),編譯器會(huì)使用多個(gè)IR階段、多種數(shù)據(jù)結(jié)構(gòu)表示代碼,并在中間階段對(duì)代碼進(jìn)行多次優(yōu)化。例如,識(shí)別冗余代碼、識(shí)別內(nèi)存逃逸等。編譯器的中間階段離不開編譯器前端記錄的細(xì)節(jié)。編譯器后端專注于生成特定目標(biāo)機(jī)器上的程序,這種程序可能是可執(zhí)行文件,也可能是需要進(jìn)一步處理的中間形態(tài)obj文件、匯編語言等。

          1-1??三階段編譯器


          需要注意的是,編譯器優(yōu)化并不是一個(gè)非常明確的概念。優(yōu)化的主要目的一般是降低程序資源的消耗,比較常見的是降低內(nèi)存與CPU的使用率。但在很多時(shí)候,這些目標(biāo)可能是相互沖突的,對(duì)一個(gè)目標(biāo)的優(yōu)化可能降低另一個(gè)目標(biāo)的效率。同時(shí),理論已經(jīng)表明有一些代碼優(yōu)化存在著NP難題,這意味著隨著代碼的增加,優(yōu)化的難度將越來越大,需要花費(fèi)的時(shí)間呈指數(shù)增長。因?yàn)檫@些原因,編譯器無法進(jìn)行最佳的優(yōu)化,所以通常采用一種折中的方案。

          Go語言編譯器一般縮寫為小寫的gc(go compiler),需要和大寫的GC(垃圾回收)進(jìn)行區(qū)分。Go語言編譯器的執(zhí)行流程可細(xì)化為多個(gè)階段,包括詞法解析、語法解析、抽象語法樹構(gòu)建、類型檢查、變量捕獲、函數(shù)內(nèi)聯(lián)、逃逸分析、閉包重寫、遍歷函數(shù)、SSA生成、機(jī)器碼生成,如圖1-2所示。


          1-2??Go語言編譯器執(zhí)行流程


          詞法解析

          和Go語言編譯器有關(guān)的代碼主要位于src/cmd/compile/internal目錄下,在后面分析中給出的文件路徑均默認(rèn)位于該目錄中。在詞法解析階段,Go語言編譯器會(huì)掃描輸入的Go源文件,并將其符號(hào)(token)化。例如“+”和“-”操作符會(huì)被轉(zhuǎn)換為_IncOp,賦值符號(hào)“:=?”會(huì)被轉(zhuǎn)換為_Define。這些token實(shí)質(zhì)上是用iota聲明的整數(shù),定義在syntax/tokens.go中。符號(hào)化保留了Go語言中定義的符號(hào),可以識(shí)別出錯(cuò)誤的拼寫。同時(shí),字符串被轉(zhuǎn)換為整數(shù)后,在后續(xù)的階段中能夠被更加高效地處理。圖1-3為一個(gè)示例,展現(xiàn)了將表達(dá)式a:=b + c(12)符號(hào)化之后的情形。代碼中聲明的標(biāo)識(shí)符、關(guān)鍵字、運(yùn)算符和分隔符等字符串都可以轉(zhuǎn)化為對(duì)應(yīng)的符號(hào)。



          圖1-3??Go語言編譯器詞法解析示例


          Go語言標(biāo)準(zhǔn)庫go/scanner、go/token也提供了許多接口用于掃描源代碼。在下例中,我們將使用這些接口模擬對(duì)Go文本文件的掃描。

          package mainimport (    "fmt"    "go/scanner"    "go/token")func main() {    src := []byte("cos(x) + 2i*sin(x) // Euler")
          // 初始化 scanner var s scanner.Scanner fset := token.NewFileSet() file := fset.AddFile("", fset.Base(), len(src)) s.Init(file, src, nil , scanner.ScanComments) // 掃描 for { pos, tok, lit := s.Scan() if tok == token.EOF { break } fmt.Printf("%s\t%s\t%q\n", fset.Position(pos), tok, lit) }}


          在上例中,src為進(jìn)行詞法掃描的表達(dá)式,可以將其模擬為一個(gè)文件并調(diào)用scanner.Scanner詞法,掃描后分別打印出token的位置、符號(hào)及其字符串字面量。每個(gè)標(biāo)識(shí)符與運(yùn)算符都被特定的token代替,例如2i被識(shí)別為復(fù)數(shù)IMAG,注釋被識(shí)別為COMMENT。

          1:1     IDENT   "cos"1:4     (       ""1:5     IDENT   "x"1:6     )       ""1:8     +       ""1:10    IMAG    "2i"1:12    *       ""1:13    IDENT   "sin"1:16    (       ""1:17    IDENT   "x"1:18    )       ""1:20    ;       "\n"1:20    COMMENT "http:// Euler"


          語法解析

          詞法解析階段結(jié)束后,需要根據(jù)Go語言中指定的語法對(duì)符號(hào)化后的Go文件進(jìn)行解析。Go語言采用了標(biāo)準(zhǔn)的自上而下的遞歸下降(Top-Down Recursive-Descent)算法,以簡單高效的方式完成無須回溯的語法掃描,核心算法位于syntax/nodes.go及syntax/parser.go中。圖1-4為Go語言編譯器對(duì)文件進(jìn)行語法解析的示意圖。在一個(gè)Go源文件中主要有包導(dǎo)入聲明(import)、靜態(tài)常量(const)、類型聲明(type)、變量聲明(var)及函數(shù)聲明。


          圖1-4??Go語言編譯器對(duì)文件進(jìn)行語法解析的示意圖


          源文件中的每一種聲明都有對(duì)應(yīng)的語法,遞歸下降通過識(shí)別初始的標(biāo)識(shí)符,例如_const,采用對(duì)應(yīng)的語法進(jìn)行解析。這種方式能夠較快地解析并識(shí)別可能出現(xiàn)的語法錯(cuò)誤。每一種聲明語法在Go語言規(guī)范中都有定義

          //包導(dǎo)入聲明ImportSpec = [ "." | PackageName ] ImportPath .ImportPath = string_lit .// 靜態(tài)常量ConstSpec = IdentifierList [ [ Type ] "=" ExpressionList ] .//類型聲明TypeSpec = identifier [ "=" ] Type .//變量聲明VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) .

          函數(shù)聲明是文件中最復(fù)雜的一類語法,因?yàn)樵诤瘮?shù)體的內(nèi)部可能有多種聲明、賦值(例如:=?)、表達(dá)式及函數(shù)調(diào)用等。例如defer語法為defer Expression ,其后必須跟一個(gè)函數(shù)或方法。每一種聲明語法或者表達(dá)式都有對(duì)應(yīng)的結(jié)構(gòu)體,例如a := b + f(89) 對(duì)應(yīng)的結(jié)構(gòu)體為賦值聲明AssignStmt。Op代表當(dāng)前的操作符,即“?:=”, Lhs與Rhs分別代表左右兩個(gè)表達(dá)式。

          AssignStmt struct {        Op       Operator         Lhs, Rhs Expr             simpleStmt    }


          語法解析丟棄了一些不重要的標(biāo)識(shí)符,例如括號(hào)“?(”,并將語義存儲(chǔ)到了對(duì)應(yīng)的結(jié)構(gòu)體中。語法聲明的結(jié)構(gòu)體擁有對(duì)應(yīng)的層次結(jié)構(gòu),這是構(gòu)建抽象語法樹的基礎(chǔ)。圖1-5為a := b + c(12)語句被語法解析后轉(zhuǎn)換為對(duì)應(yīng)的syntax.AssignStmt結(jié)構(gòu)體之后的情形。最頂層的Op操作符為token.Def(:=?)。Lhs表達(dá)式類型為標(biāo)識(shí)符syntax.Name,值為標(biāo)識(shí)符“a”。Rhs表達(dá)式為syntax.Operator加法運(yùn)算。加法運(yùn)算左邊為標(biāo)識(shí)符“b”,右邊為函數(shù)調(diào)用表達(dá)式,類型為CallExpr。其中,函數(shù)名c的類型為syntax.Name,參數(shù)為常量類型syntax.BasicLit,代表數(shù)字12。


          圖1-5??特定表達(dá)式的語法解析示例


          Go語言可執(zhí)行文件的生成離不開編譯器所做的復(fù)雜工作,如果不理解Go語言的編譯器,那么對(duì)Go語言的理解是不完整的。Go語言的編譯器、運(yùn)行時(shí),本身就是用Go語言寫出的既復(fù)雜又精巧的程序;探究語言設(shè)計(jì)、語法特性,本身就是學(xué)習(xí)程序設(shè)計(jì)與架構(gòu)、數(shù)據(jù)結(jié)構(gòu)與算法等知識(shí)的絕佳途徑。學(xué)習(xí)底層原理能夠幫助我們更好地了解Go語言的語法,做出合理的性能優(yōu)化,設(shè)計(jì)科學(xué)的程序架構(gòu),監(jiān)控程序的運(yùn)行狀態(tài),排查復(fù)雜的程序異常問題,開發(fā)出檢查協(xié)程泄露、語法等問題的高級(jí)工具,理解Go語言的局限性,從而在不同場(chǎng)景下做出合理抉擇。

          編譯階段包括詞法解析、語法解析、抽象語法樹構(gòu)建、類型檢查、變量捕獲、函數(shù)內(nèi)聯(lián)、逃逸分析、閉包重寫、遍歷并編譯函數(shù)、SSA生成、機(jī)器碼生成。編譯器不僅能準(zhǔn)確地表達(dá)語義,還能對(duì)代碼進(jìn)行一定程度的優(yōu)化。可以看到,Go語言的很多語法檢查、語法特性都依賴編譯時(shí)。理解編譯時(shí)的基本流程、優(yōu)化方案及一些調(diào)試技巧有助于寫出更好的程序。

          目前市面上鮮有系統(tǒng)介紹Go語言底層實(shí)現(xiàn)原理的書籍,如果你想系統(tǒng)了解學(xué)習(xí)更多,今天給大家推薦這本新書書,書中系統(tǒng)性地介紹Go語言在編譯時(shí)、運(yùn)行時(shí)以及語法特性等層面的底層原理和更好的使用方法。

          本書語言通俗易懂,書中有系統(tǒng)權(quán)威的知識(shí)解構(gòu)、精美的示意圖,并對(duì)照源碼和參考文獻(xiàn)字斟句酌,在一線大規(guī)模系統(tǒng)中提煉出設(shè)計(jì)哲學(xué)與避坑方法,對(duì)于編譯時(shí)、運(yùn)行時(shí)及垃圾回收的精彩講解彌補(bǔ)了國內(nèi)的多項(xiàng)缺陷,這本罕見的誠意之作必將陪伴讀者實(shí)現(xiàn)最艱苦的能力跨越,你想要的都會(huì)到來……

          內(nèi)容簡介

          本書由21章組成,這21章可以分為6部分。

          • 第1~8章為第1部分,介紹Go語言的基礎(chǔ)——編譯時(shí)及類型系統(tǒng)。包括浮點(diǎn)數(shù)、切片、哈希表等類型以及類型轉(zhuǎn)換的原理。

          • 第9~11章為第2部分,介紹程序運(yùn)行重要的組成部分——函數(shù)與棧。包括棧幀布局、棧擴(kuò)容、棧調(diào)試的原理,并介紹了延遲調(diào)用、異常與異常捕獲的原理。

          • 第12、13章為第3部分,介紹Go語言程序設(shè)計(jì)的關(guān)鍵——接口。包括如何正確合理地使用接口構(gòu)建程序、接口的實(shí)現(xiàn)原理和可能遇到的問題,并探討了接口之上的反射原理。

          • 第14~17章為第4部分,介紹Go語言并發(fā)的核心——協(xié)程與通道。詳細(xì)論述了協(xié)程的本質(zhì)以及運(yùn)行時(shí)調(diào)度器的調(diào)度時(shí)機(jī)與策略。介紹了通過通信來共享內(nèi)存的通道本質(zhì)以及通道的多路復(fù)用原理,并探討了并發(fā)控制、數(shù)據(jù)爭用問題的解決辦法及鎖的本質(zhì)。

          • 第18~20章為第5部分,介紹Go語言運(yùn)行時(shí)最復(fù)雜的模塊——內(nèi)存管理與垃圾回收。詳細(xì)論述了Go語言中實(shí)現(xiàn)內(nèi)存管理方法及垃圾回收的詳細(xì)步驟。

          • 第21章為第6部分,介紹Go語言可視化工具——pprof與trace。詳細(xì)論述了通過工具排查問題、觀察系統(tǒng)運(yùn)行狀態(tài)的方法與實(shí)現(xiàn)原理。

          本書作者

          鄭建勛

          Golang contributor(Go語言垃圾回收模塊代碼貢獻(xiàn)者)、Go語言精度庫shopspring/decimal核心貢獻(xiàn)者。滴滴高級(jí)研發(fā)工程師。擁有豐富的分布式、高并發(fā)、大規(guī)模微服務(wù)集群的開發(fā)設(shè)計(jì)經(jīng)驗(yàn)。

          微信公眾號(hào)“gopher夢(mèng)工廠”作者,知名go語言原創(chuàng)博主,51CTO學(xué)堂高級(jí)講師、極客時(shí)間“每日一課”講師。有豐富的教育經(jīng)驗(yàn),想讀者之所想。相信這部系統(tǒng)且深入淺出的作品,會(huì)是讀者打怪升級(jí)的最佳輔助。



          專家力薦

          這是一本Go語言的初學(xué)者和進(jìn)階學(xué)者都可以受益的書。它不僅僅介紹了Go的語言特性,還深入這些特性背后的設(shè)計(jì)考量、編譯器及語言實(shí)現(xiàn)的細(xì)節(jié)。授人以魚和授人以漁在本書里面一起得到了體現(xiàn)。更難得的是,本書并沒有粘貼大段的代碼,而是以圖文的形式將復(fù)雜的概念解釋清楚,降低了閱讀和理解的難度,使得讀者不會(huì)望“底層”和“深入”二詞而卻步。

          ?——葉紹志博士??Shopee技術(shù)委員會(huì)主席、順豐速運(yùn)前CTO、Google前主任工程師

          贈(zèng)書活動(dòng)

          關(guān)注公眾帳號(hào)云原生實(shí)驗(yàn)室,后臺(tái)發(fā)送暗號(hào):gop 獲取抽獎(jiǎng)入口

          ??關(guān)注公眾號(hào),回復(fù) gop 即可參與

          本次將隨機(jī)抽取 5 位,每人獲得《Go 語言底層原理剖析》書籍一本,感謝中國電子工業(yè)出版社提供的書籍

          活動(dòng)截止時(shí)間:10月21日18:00

          沒抽中的小伙伴也可以通過如下入口直接購買~

          瀏覽 59
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  婷婷淫淫网 | 热99在线 | 久久精产国99精产国高潮麻豆 | 国产无码123 | 亚洲国产精品视频 |