欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go語(yǔ)言區(qū)別于其他語(yǔ)言的特性

 更新時(shí)間:2021年10月08日 17:24:40   作者:海擁  
在本文中,今天這篇文章將給大家介紹一下 Go 與其他語(yǔ)言不同的 9 個(gè)特性,需要的朋友可以參考下面文章的具體內(nèi)容

前言:

隨著編程語(yǔ)言的發(fā)展,Go 還很年輕。它于 2009 年 11 月 10 日首次發(fā)布。其創(chuàng)建者Robert Griesemer Rob Pike Ken ThompsonGoogle 工作,在那里大規(guī)模擴(kuò)展的挑戰(zhàn)激勵(lì)他們將 Go 設(shè)計(jì)為一種快速有效的編程解決方案,用于具有大型代碼庫(kù)、管理由多個(gè)開(kāi)發(fā)人員,具有嚴(yán)格的性能要求,并跨越多個(gè)網(wǎng)絡(luò)和處理核心。 Go 的創(chuàng)始人在創(chuàng)建他們的新語(yǔ)言時(shí)也借此機(jī)會(huì)學(xué)習(xí)了其他編程語(yǔ)言的優(yōu)點(diǎn)、缺點(diǎn)和漏洞。結(jié)果是一種干凈、清晰和實(shí)用的語(yǔ)言,具有相對(duì)較少的命令和功能集。

1. Go 總是在構(gòu)建中包含二進(jìn)制文件

Go 運(yùn)行時(shí)提供內(nèi)存分配、垃圾收集、并發(fā)支持和網(wǎng)絡(luò)等服務(wù)。它被編譯到每個(gè) Go 二進(jìn)制文件中。這與許多其他語(yǔ)言不同,其中許多語(yǔ)言使用需要與程序一起安裝才能正常工作的虛擬機(jī)。

將運(yùn)行時(shí)直接包含在二進(jìn)制文件中使得分發(fā)和運(yùn)行 Go 程序變得非常容易,并避免了運(yùn)行時(shí)和程序之間的不兼容問(wèn)題。Python、Ruby JavaScript 等語(yǔ)言的虛擬機(jī)也沒(méi)有針對(duì)垃圾收集和內(nèi)存分配進(jìn)行優(yōu)化,這解釋了 Go 相對(duì)于其他類似語(yǔ)言的優(yōu)越速度。例如,Go 將盡可能多的存儲(chǔ)在堆棧中,其中數(shù)據(jù)按順序排列以便比堆更快地訪問(wèn)。稍后會(huì)詳細(xì)介紹。

關(guān)于 Go 的靜態(tài)二進(jìn)制文件的最后一件事是,因?yàn)椴恍枰\(yùn)行外部依賴項(xiàng),所以它們啟動(dòng)得非???。如果您使用Google App Engine 之類的服務(wù),這是一種在 Google Cloud 上運(yùn)行的平臺(tái)即服務(wù),它可以將您的應(yīng)用程序縮減到零實(shí)例以節(jié)省云成本,這將非常有用。當(dāng)收到新請(qǐng)求時(shí),App Engine 可以在眨眼間啟動(dòng) Go 程序的一個(gè)實(shí)例。在 Python 或 Node 中的相同體驗(yàn)通常會(huì)導(dǎo)致 3-5 秒(或更長(zhǎng)時(shí)間)的等待,因?yàn)樗璧奶摂M環(huán)境也會(huì)與新實(shí)例一起啟動(dòng)。

2. Go 沒(méi)有針對(duì)程序依賴的集中托管服務(wù)

為了訪問(wèn)已發(fā)布的 Go 程序,開(kāi)發(fā)人員不依賴集中托管的服務(wù),例如Java 的Maven CentralJavaScript的NPM注冊(cè)表。相反,項(xiàng)目通過(guò)其源代碼存儲(chǔ)庫(kù)(最常見(jiàn)的是 Github)共享。在go install命令行允許以這種方式下載庫(kù)。 為什么我喜歡這個(gè)功能?我一直認(rèn)為像 Maven Central、PIP 和 NPM 這樣的集中托管的依賴服務(wù)有點(diǎn)令人生畏的黑盒子,也許可以抽象出下載和安裝依賴項(xiàng)的麻煩,但不可避免地會(huì)在依賴項(xiàng)錯(cuò)誤時(shí)引發(fā)可怕的心跳停止發(fā)生。

此外,將的的模塊提供給其他人就像將其放入版本控制系統(tǒng)一樣簡(jiǎn)單,這是分發(fā)程序的一種非常簡(jiǎn)單的方式。

3. Go 是按值調(diào)用的

在 Go 中,當(dāng)你提供一個(gè)原始值(數(shù)字、布爾值或字符串)或一個(gè)結(jié)構(gòu)體(類對(duì)象的粗略等價(jià)物)作為函數(shù)的參數(shù)時(shí),Go 總是會(huì)復(fù)制變量的值。

Java、Python JavaScript 等許多其他語(yǔ)言中,原語(yǔ)是按值傳遞的,但對(duì)象(類實(shí)例)是按引用傳遞的,這意味著接收函數(shù)實(shí)際上接收的是指向原始對(duì)象的指針,而不是其副本。在接收函數(shù)中對(duì)對(duì)象所做的任何更改都會(huì)反映在原始對(duì)象中。

在 Go 中,結(jié)構(gòu)體和原語(yǔ)默認(rèn)按值傳遞,可以選擇傳遞指針,通過(guò)使用星號(hào)運(yùn)算符:

// 按值傳遞
func MakeNewFoo(f Foo ) (Foo, error) { 
   f.Field1 = "New val" 
   f.Field2 = f.Field2 + 1 
   return f, nil 
}

上述函數(shù)接收 Foo 的副本并返回一個(gè)新的 Foo 對(duì)象。

// 通過(guò)引用傳遞
func MutateFoo(f *Foo ) error { 
   f.Field1 = "New val" 
   f.Field2 = 2 
   return nil 
}

上面的函數(shù)接收一個(gè)指向 Foo 的指針并改變?cè)紝?duì)象。

按值調(diào)用與按引用調(diào)用的這種明顯區(qū)別使您的意圖顯而易見(jiàn),并降低了調(diào)用函數(shù)無(wú)意中改變傳入對(duì)象的可能性(當(dāng)它不應(yīng)該發(fā)生時(shí)(許多初學(xué)者開(kāi)發(fā)人員很難做到這一點(diǎn))握緊)。

正如麻省理工總結(jié)的:“可變性使得理解你的程序在做什么變得更加困難,并且更難以執(zhí)行契約”

此外,按值調(diào)用顯著減少了垃圾收集器的工作,這意味著應(yīng)用程序更快、內(nèi)存效率更高。這篇文章得出的結(jié)論是,指針追蹤(從堆中檢索指針值)比從連續(xù)堆棧中檢索值慢 10 到 20 倍。要記住的一個(gè)很好的經(jīng)驗(yàn)法則是:從內(nèi)存中讀取的最快方法是順序讀取,這意味著將隨機(jī)存儲(chǔ)在 RAM 中的指針數(shù)量減少到最少。

4. 'defer' 關(guān)鍵字

NodeJS 中,在我開(kāi)始使用knex.js之前,我會(huì)通過(guò)創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)池來(lái)手動(dòng)管理我的代碼中的數(shù)據(jù)庫(kù)連接,然后在每個(gè)函數(shù)中從池中打開(kāi)一個(gè)新連接,一旦所需的數(shù)據(jù)庫(kù) CRUD 功能已完成。

這有點(diǎn)像維護(hù)噩夢(mèng),因?yàn)槿绻覜](méi)有在每個(gè)函數(shù)結(jié)束時(shí)釋放連接,未釋放的數(shù)據(jù)庫(kù)連接的數(shù)量會(huì)慢慢增長(zhǎng),直到池中沒(méi)有更多可用連接,然后中斷應(yīng)用程序。

現(xiàn)實(shí)情況是,程序經(jīng)常需要釋放、清理和拆除資源、文件、連接等,因此 Go 引入了defer關(guān)鍵字作為管理這些的有效方式。

任何以defer開(kāi)頭的語(yǔ)句都會(huì)延遲對(duì)它的調(diào)用,直到周圍的函數(shù)退出。這意味著您可以將清理/拆卸代碼放在函數(shù)的頂部(很明顯),知道一旦函數(shù)完成它就會(huì)如此。

func main() {                        
    if len(os.Args) < 2 {   
        log.Fatal("no file specified")
    }  
    f, err := os.Open(os.Args[1])                        
    if err != nil {                         
        log.Fatal(err)                        
    }                        
    defer f.Close()                        
    data := make([]byte, 2048)                        
    for {                         
        count, err := f.Read(data)                                               
        os.Stdout.Write(data[:count])                        
        if err != nil {                          
            if err != io.EOF {                           
                log.Fatal(err)                          
            }                          
            break                         
        }                        
    }                       
}

在上面的例子中,文件關(guān)閉方法被推遲了。我喜歡這種在函數(shù)頂部聲明你的內(nèi)務(wù)處理意圖的模式,然后忘記它,知道一旦函數(shù)退出它就會(huì)完成它的工作。

5. Go 采用了函數(shù)式編程的最佳特性

函數(shù)式編程是一種高效且富有創(chuàng)造性的范式,幸運(yùn)的是 Go 采用了函數(shù)式編程的最佳特性。在Go中:

  • 函數(shù)是值,這意味著它們可以作為值添加到映射中,作為參數(shù)傳遞給其他函數(shù),設(shè)置為變量,并從函數(shù)返回(稱為“高階函數(shù)”,在 Go 中經(jīng)常使用裝飾器創(chuàng)建中間件圖案)。
  • 可以創(chuàng)建和自動(dòng)調(diào)用匿名函數(shù)。
  • 在其他函數(shù)內(nèi)聲明的函數(shù)允許閉包(在函數(shù)內(nèi)聲明的函數(shù)能夠訪問(wèn)和修改在外部函數(shù)中聲明的變量)。在慣用的 Go 中,閉包被廣泛使用來(lái)限制函數(shù)的范圍,并設(shè)置函數(shù)然后在其邏輯中使用的狀態(tài)。

func StartTimer (name string) func(){
    t := time.Now()
    log.Println(name, "started")
    return func() {
        d := time.Now().Sub(t)
        log.Println(name, "took", d)
    }
}
func RunTimer() {
    stop := StartTimer("My timer")
    defer stop()
    time.Sleep(1 * time.Second)
}

上面是一個(gè)閉包的例子。'StartTimer' 函數(shù)返回一個(gè)新函數(shù),它通過(guò)閉包可以訪問(wèn)在其出生范圍內(nèi)設(shè)置的 't' 值。然后,此函數(shù)可以將當(dāng)前時(shí)間與“t”的值進(jìn)行比較,從而創(chuàng)建一個(gè)有用的計(jì)時(shí)器。感謝Mat Ryer的這個(gè)例子。

6. Go 有隱式接口

任何閱讀過(guò)有關(guān)SOLID編碼和設(shè)計(jì)模式的文獻(xiàn)的人都可能聽(tīng)說(shuō)過(guò)“優(yōu)先組合勝過(guò)繼承”的口頭禪。簡(jiǎn)而言之,這表明您應(yīng)該將業(yè)務(wù)邏輯分解為不同的接口,而不是依賴于來(lái)自父類的屬性和邏輯的分層繼承。

另一個(gè)流行的方法是“為接口編程,而不是實(shí)現(xiàn)”: API 應(yīng)該只發(fā)布其預(yù)期行為的契約(其方法簽名),而不是有關(guān)如何實(shí)現(xiàn)該行為的詳細(xì)信息。

這兩者都表明接口在現(xiàn)代編程中的重要性。

因此,Go 支持接口也就不足為奇了。事實(shí)上,接口是 Go 中唯一的抽象類型。

然而,與其他語(yǔ)言不同,Go 中的接口不是顯式實(shí)現(xiàn)的,而是隱式實(shí)現(xiàn)的。具體類型不聲明它實(shí)現(xiàn)了接口。相反,如果為該具體類型設(shè)置的方法集包含底層接口的所有方法集,則Go 認(rèn)為該對(duì)象實(shí)現(xiàn)了 interface。

這種隱式接口實(shí)現(xiàn)(正式稱為結(jié)構(gòu)類型)允許 Go 強(qiáng)制執(zhí)行類型安全和解耦,保持動(dòng)態(tài)語(yǔ)言中表現(xiàn)出的大部分靈活性。

相比之下,顯式接口將客戶端和實(shí)現(xiàn)綁定在一起,例如,在 Java 中替換依賴項(xiàng)比在 Go 中困難得多。

// 這是一個(gè)接口聲明(稱為L(zhǎng)ogic)
type Logic interface { 
    Process (data string) string 
}

type LogicProvider struct {}
// 這是 LogicProvider 上名為“Process”的方法 struct
 func (lp LogicProvider) Process (data string) string { 
    // 業(yè)務(wù)邏輯
}
// 這是具有 Logic 接口作為屬性的客戶端結(jié)構(gòu)
type Client struct { 
    L Logic 
}
func(c Client) Program() { 
    // 從某處獲取數(shù)據(jù)
    cLProcess(data) 
}
func main() { 
    c := Client { 
        L: LogicProvider{},  
     } 
    c.Program() 
}

LogicProvider 中沒(méi)有任何聲明表示它符合Logic接口。這意味著客戶端將來(lái)可以輕松替換其邏輯提供程序,只要該邏輯提供程序包含底層接口 ( Logic ) 的所有方法集。

7.錯(cuò)誤處理

Go 中的錯(cuò)誤處理方式與其他語(yǔ)言大不相同。簡(jiǎn)而言之,Go 通過(guò)返回一個(gè) error 類型的值作為函數(shù)的最后一個(gè)返回值來(lái)處理錯(cuò)誤。

當(dāng)函數(shù)按預(yù)期執(zhí)行時(shí),錯(cuò)誤參數(shù)返回nil,否則返回錯(cuò)誤值。調(diào)用函數(shù)然后檢查錯(cuò)誤返回值,并處理錯(cuò)誤,或拋出自己的錯(cuò)誤。

// 函數(shù)返回一個(gè)整數(shù)和一個(gè)錯(cuò)誤
func calculateRemainder(numerator int, denominator int) ( int, error ) { 
   //
   if denominator == 0 { 
      return 9, errors.New("denominator is 0"
    }
   // 沒(méi)有錯(cuò)誤返回
   return numerator / denominator, nil
 }

Go 以這種方式運(yùn)行是有原因的:它迫使編碼人員考慮異常并正確處理它們。傳統(tǒng)的 try-catch 異常還會(huì)在代碼中添加至少一個(gè)新的代碼路徑,并以難以遵循的方式縮進(jìn)代碼。Go 更喜歡將“快樂(lè)路徑”視為非縮進(jìn)代碼,在“快樂(lè)路徑”完成之前識(shí)別并返回任何錯(cuò)誤。

8.并發(fā)

可以說(shuō)是 Go 最著名的特性,并發(fā)允許處理在機(jī)器或服務(wù)器上的可用內(nèi)核數(shù)量上并行運(yùn)行。當(dāng)單獨(dú)的進(jìn)程不相互依賴(不需要順序運(yùn)行)并且時(shí)間性能至關(guān)重要時(shí),并發(fā)性最有意義。這通常是 I/O 要求的情況,其中讀取或?qū)懭氪疟P(pán)或網(wǎng)絡(luò)的速度比除最復(fù)雜的內(nèi)存中進(jìn)程之外的所有進(jìn)程慢幾個(gè)數(shù)量級(jí)。 函數(shù)調(diào)用前的“ go ”關(guān)鍵字將同時(shí)運(yùn)行該函數(shù)。

func process(val int) int { 
   // 用 val 做一些事情
}
// 對(duì)于 'in' 中的每個(gè)值,同時(shí)運(yùn)行 process 函數(shù),
// 并將 process 的結(jié)果讀取到 'out'
 func runConcurrently(in <-chan int, out chan<- int){ 
   go func() { 
       for val := range in { 
            result := process(val) 
            out <- result   
       } 
   } 
}

Go 中的并發(fā)是一項(xiàng)深入且相當(dāng)高級(jí)的功能,但在有意義的地方,它提供了一種有效的方法來(lái)確保程序的最佳性能。

9. Go 標(biāo)準(zhǔn)庫(kù)

Go 有一個(gè)“包含電池”的理念,現(xiàn)代編程語(yǔ)言的許多要求都被納入標(biāo)準(zhǔn)庫(kù),這使程序員的生活變得更加簡(jiǎn)單。 如前所述,Go 是一種相對(duì)年輕的語(yǔ)言,這意味著標(biāo)準(zhǔn)庫(kù)中可以滿足現(xiàn)代應(yīng)用程序的許多問(wèn)題/要求。

一方面,Go 為網(wǎng)絡(luò)(特別是 HTTP/2)和文件管理提供了世界一流的支持。它還提供原生 JSON 編碼和解碼。因此,設(shè)置服務(wù)器來(lái)處理 HTTP 請(qǐng)求并返回響應(yīng)(JSON 或其他)非常簡(jiǎn)單,這解釋了 Go 在基于 REST 的 HTTP Web 服務(wù)開(kāi)發(fā)中的流行。

正如Mat Ryer還指出的那樣,標(biāo)準(zhǔn)庫(kù)是開(kāi)源的,是學(xué)習(xí) Go 最佳實(shí)踐的絕佳方式。

到此這篇關(guān)于Go 有別于其他語(yǔ)言的九個(gè)特性 的文章就介紹到這了,更多相關(guān)Go 有別于其他語(yǔ)言的特性 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用Go進(jìn)行單元測(cè)試的實(shí)現(xiàn)

    使用Go進(jìn)行單元測(cè)試的實(shí)現(xiàn)

    這篇文章主要介紹了使用Go進(jìn)行單元測(cè)試的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • 淺析Go使用定時(shí)器時(shí)如何避免潛在的內(nèi)存泄漏陷阱

    淺析Go使用定時(shí)器時(shí)如何避免潛在的內(nèi)存泄漏陷阱

    這篇文章來(lái)和大家一起探討一下Go?中如何高效使用?timer,特別是與select?一起使用時(shí),如何防止?jié)撛诘膬?nèi)存泄漏問(wèn)題,感興趣的可以了解下
    2024-01-01
  • Go分布式鏈路追蹤實(shí)戰(zhàn)探索

    Go分布式鏈路追蹤實(shí)戰(zhàn)探索

    這篇文章主要為大家介紹了Go分布式鏈路追蹤實(shí)戰(zhàn)示例探索,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • Go語(yǔ)言kube-scheduler深度剖析與開(kāi)發(fā)之pod調(diào)度

    Go語(yǔ)言kube-scheduler深度剖析與開(kāi)發(fā)之pod調(diào)度

    這篇文章主要為大家介紹了Go語(yǔ)言kube-scheduler深度剖析與開(kāi)發(fā),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • Go語(yǔ)言中make和new函數(shù)的用法與區(qū)別

    Go語(yǔ)言中make和new函數(shù)的用法與區(qū)別

    這篇文章介紹了Go語(yǔ)言中make和new函數(shù)的用法與區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07
  • golang中l(wèi)og包自定義輸出日志格式與寫(xiě)入到文件

    golang中l(wèi)og包自定義輸出日志格式與寫(xiě)入到文件

    這篇文章主要給大家介紹了關(guān)于golang中l(wèi)og包自定義輸出日志格式與寫(xiě)入到文件的相關(guān)資料,日志輸出在任何項(xiàng)目中都極其重要,是有助于后續(xù)我們排查解決程序BUG,需要的朋友可以參考下
    2023-06-06
  • golang?用msgpack高效序列化的案例

    golang?用msgpack高效序列化的案例

    msgpack是一個(gè)非常受歡迎的Go序列化庫(kù),具有很好的跨語(yǔ)言支持,這篇文章主要介紹了golang?用msgpack高效序列化的相關(guān)知識(shí),需要的朋友可以參考下
    2023-05-05
  • Go語(yǔ)言中嵌入C語(yǔ)言的方法

    Go語(yǔ)言中嵌入C語(yǔ)言的方法

    這篇文章主要介紹了Go語(yǔ)言中嵌入C語(yǔ)言的方法,實(shí)例分析了Go語(yǔ)言中cgo工具的使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-02-02
  • GO語(yǔ)io包的常用接口

    GO語(yǔ)io包的常用接口

    這篇文章主要介紹了GO語(yǔ)io包的常用接口,分析了GO語(yǔ)言接口的概念與功能,并實(shí)例列舉了幾個(gè)最常用的接口的用法,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2014-12-12
  • RabbitMQ延時(shí)消息隊(duì)列在golang中的使用詳解

    RabbitMQ延時(shí)消息隊(duì)列在golang中的使用詳解

    延時(shí)隊(duì)列常使用在某些業(yè)務(wù)場(chǎng)景,使用延時(shí)隊(duì)列可以簡(jiǎn)化系統(tǒng)的設(shè)計(jì)和開(kāi)發(fā)、提高系統(tǒng)的可靠性和可用性、提高系統(tǒng)的性能,下面我們就來(lái)看看如何在golang中使用RabbitMQ的延時(shí)消息隊(duì)列吧
    2023-11-11

最新評(píng)論