一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術(shù)及教程分享平臺!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Golang - Go:十個(gè)與眾不同的特性,你知道嗎?

Go:十個(gè)與眾不同的特性,你知道嗎?

2022-01-05 23:14幽鬼程序員ug Golang

Go 作為一門相對較新的語言,能夠脫穎而出,肯定是多方面的原因。本文聊聊它不同于其他語言的 10 個(gè)特性。

Go:十個(gè)與眾不同的特性,你知道嗎?

大家好,我是程序員幽鬼。

Go 作為一門相對較新的語言,能夠脫穎而出,肯定是多方面的原因。本文聊聊它不同于其他語言的 10 個(gè)特性。

Go 的創(chuàng)建者 Robert Griesemer[1] 、Rob Pike[2] 和 Ken Thompson[3] 在 Google 工作,在那里,大規(guī)模擴(kuò)展的挑戰(zhàn)激發(fā)了他們將 Go 設(shè)計(jì)為具有大型代碼庫的項(xiàng)目的快速高效的編程解決方案,由多個(gè)開發(fā)人員管理,具有嚴(yán)格的性能要求,并跨越多個(gè)網(wǎng)絡(luò)和處理核心。

Go 的創(chuàng)始人在創(chuàng)建新語言時(shí)也抓住了這個(gè)機(jī)會(huì),從其他編程語言的優(yōu)勢,劣勢和疏忽中學(xué)習(xí)。結(jié)果是一種干凈,清晰和實(shí)用的語言,具有相對較小的命令和特性集。

本文將介紹 Go 的 10 個(gè)特性,這些特性(根據(jù)我個(gè)人的觀察)將其與其他語言區(qū)分開來。

1. Go 始終在構(gòu)建中包含 runtime

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

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

關(guān)于 Go 的靜態(tài)二進(jìn)制文件的最后一件事是,由于不需要運(yùn)行外部依賴項(xiàng),因此它們的啟動(dòng)速度非???。如果你使用像 Google App Engine[6] 這樣的服務(wù),這將非常有用,這是一種在 Google Cloud 上運(yùn)行的平臺即服務(wù),可以將你的應(yīng)用程序擴(kuò)展到零實(shí)例以節(jié)省云成本。當(dāng)有新的請求出現(xiàn)時(shí),App Engine 可以在眨眼間啟動(dòng)你的 Go 程序?qū)嵗?。?Python 或 Node 中相同的體驗(yàn)通常會(huì)導(dǎo)致 3-5 秒的等待(或更長時(shí)間),因?yàn)樗璧奶摂M環(huán)境也與新實(shí)例一起旋轉(zhuǎn)。

2. Go 沒有集中托管的程序依賴服務(wù)

為了訪問已發(fā)布的 Go 程序,開發(fā)人員不依賴于集中托管的服務(wù),例如用于 Java 的Maven Central[7]或用于 JavaScript 的NPM[8]。相反,項(xiàng)目通過其源代碼存儲庫(通常是 GitHub)共享。go get/install 命令行允許以這種方式下載存儲庫。

為什么我喜歡這個(gè)功能?我一直認(rèn)為集中托管的依賴服務(wù)(如 Maven Central、PIP 和 NPM)有著令人生畏的黑匣子,可能會(huì)抽象出下載和安裝依賴項(xiàng)(以及依賴項(xiàng)的依賴項(xiàng))的麻煩,但當(dāng)依賴項(xiàng)錯(cuò)誤發(fā)生時(shí),不可避免地會(huì)引發(fā)可怕的心跳加速(我經(jīng)歷過太多了,無法計(jì)數(shù))。

很多時(shí)候,我發(fā)現(xiàn)令人沮喪的是,我從來沒有完全理解它們內(nèi)部是如何工作的。通過取消中央服務(wù),安裝,版本控制和管理 Go 項(xiàng)目的依賴項(xiàng)的過程非常清晰,從而更加清晰。(當(dāng)然,也有人喜歡集中托管)

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

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

在 Go 中,當(dāng)你提供基本類型(數(shù)字、布爾值或字符串)或結(jié)構(gòu)(類對象的大致等效項(xiàng))作為函數(shù)的參數(shù)時(shí),Go 始終會(huì)創(chuàng)建變量值的副本。

在許多其他語言如 Java,Python 和 JavaScript 中,基本類型是通過值傳遞[9]的,但是對象(類實(shí)例)是通過引用傳遞的,這意味著接收函數(shù)實(shí)際上接收到指向原始對象的指針,而不是其副本。

這意味著在接收函數(shù)中對對象所做的任何更改都將反映在原始對象中。

在 Go 中,結(jié)構(gòu)和基本類型默認(rèn)按值傳遞,可以選擇通過使用星號運(yùn)算符傳遞指針[10]:

  1. // pass by value
  2. func MakeNewFoo(f Foo) (Foo, error) {
  3. f.Field1 = "New val"
  4. f.Field2 = f.Field2 + 1
  5. return f, nil
  6. }

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

  1. // pass by reference
  2. func MutateFoo(f *Foo) error {
  3. f.Field1 = "New val"
  4. f.Field2 = 2
  5. return nil
  6. }

上面的函數(shù)接收指向 Foo 的指針并改變原始對象。

這種按值調(diào)用與按引用調(diào)用的明顯區(qū)別使你的意圖顯而易見,并減少了調(diào)用函數(shù)無意中改變傳入對象的可能性(這是許多初學(xué)者開發(fā)人員難以掌握的)。

正如麻省理工學(xué)院總結(jié)[11]的那樣:"可變性使得理解你的程序在做什么變得更加困難,而執(zhí)行合約也更難"。

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

4. defer 關(guān)鍵字

在 NodeJS 中,在我開始使用knex.js[13]之前,我會(huì)在代碼中手動(dòng)管理數(shù)據(jù)庫連接,方法是創(chuàng)建一個(gè)數(shù)據(jù)庫池,然后在每個(gè)函數(shù)的池中打開一個(gè)新連接,一旦所需的數(shù)據(jù)庫 CRUD 功能完成,就會(huì)在函數(shù)結(jié)束時(shí)釋放連接。

這有點(diǎn)像維護(hù)的噩夢,因?yàn)槿绻以诿總€(gè)函數(shù)結(jié)束時(shí)不釋放連接,未釋放的數(shù)據(jù)庫連接的數(shù)量將慢慢增長,直到池中沒有更多的可用連接,然后中斷應(yīng)用程序。

現(xiàn)實(shí)情況是,程序通常必須發(fā)布,清理和執(zhí)行資源,文件,連接等,因此 Go 引入了defer關(guān)鍵字作為管理這一點(diǎn)的有效方法。

任何前面帶有defer的語句都會(huì)延遲其調(diào)用,直到周圍的函數(shù)退出。這意味著你可以將清理/拆卸代碼放在函數(shù)的頂部(很明顯),知道一旦函數(shù)完成,它就會(huì)完成它的工作。

  1. func main() {
  2. if len(os.Args) < 2 {
  3. log.Fatal("no file specified")
  4. }
  5. f, err := os.Open(os.Args[1])
  6. if err != nil {
  7. log.Fatal(err)
  8. }
  9. defer f.Close()
  10. data := make([]byte, 2048)
  11. for {
  12. count, err := f.Read(data)
  13. os.Stdout.Write(data[:count])
  14. if err != nil {
  15. if err != io.EOF {
  16. log.Fatal(err)
  17. }
  18. break
  19. }
  20. }
  21. }

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

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

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

— 函數(shù)是值,這意味著它們可以作為值添加到 map 中,作為參數(shù)傳遞到其他函數(shù)中,設(shè)置為變量,并從函數(shù)返回(稱為"高階函數(shù)",在 Go 中經(jīng)常用于使用裝飾器模式創(chuàng)建中間件)。

— 匿名函數(shù)可以創(chuàng)建并自動(dòng)調(diào)用。

— 在其他函數(shù)中聲明的函數(shù)允許閉包(其中在函數(shù)內(nèi)部聲明的函數(shù)能夠訪問和修改在外部函數(shù)中聲明的變量)。在慣用的 Go 中,閉包被廣泛使用,限制了函數(shù)的作用域,并設(shè)置了函數(shù)在其邏輯中使用的狀態(tài)。

  1. func StartTimer (name string) func(){
  2. t := time.Now()
  3. log.Println(name, "started")
  4. return func() {
  5. d := time.Now().Sub(t)
  6. log.Println(name, "took", d)
  7. }
  8. }
  9. func RunTimer() {
  10. stop := StartTimer("My timer")
  11. defer stop()
  12. time.Sleep(1 * time.Second)
  13. }

以上是閉包的一個(gè)例子。'StartTimer' 函數(shù)返回一個(gè)新函數(shù),該函數(shù)通過閉包可以訪問在其啟動(dòng)作用域中設(shè)置的 't' 值。然后,此函數(shù)可以將當(dāng)前時(shí)間與 "t" 的值進(jìn)行比較,從而創(chuàng)建一個(gè)有用的計(jì)時(shí)器。感謝Mat Ryer[14]的這個(gè)例子。

6. Go 有隱式接口實(shí)現(xiàn)

任何讀過SOLID[15]編碼和設(shè)計(jì)模式[16]文獻(xiàn)的人都可能聽說過 "偏愛組合而不是繼承" 的口頭禪。簡而言之,這表明你應(yīng)該將業(yè)務(wù)邏輯分解為不同的接口,而不是依賴于父類中屬性和邏輯的分層繼承。

另一個(gè)流行的方法是 "面向接口編程,而不是實(shí)現(xiàn)":API 應(yīng)該只發(fā)布其預(yù)期行為的契約(其方法簽名),但不能詳細(xì)介紹如何實(shí)現(xiàn)該行為。

這兩者都指出了接口在現(xiàn)代編程中的至關(guān)重要性。

因此,毫不奇怪,Go 支持接口。事實(shí)上,接口是 Go 中唯一的抽象類型。

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

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

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

  1. // this is an interface declaration (called Logic)
  2. type Logic interface {
  3. Process(data string) string
  4. }
  5. type LogicProvider struct {}
  6. // this is a method called 'Process' on the LogicProvider struct
  7. func (lp LogicProvider) Process(data string) string {
  8. // business logic
  9. }
  10. // this is the client struct with the Logic interface as a property
  11. type Client struct {
  12. L Logic
  13. }
  14. func(c Client) Program() {
  15. // get data from somewhere
  16. c.L.Process(data)
  17. }
  18. func main() {
  19. c := Client {
  20. L: LogicProvider{},
  21. }
  22. c.Program()
  23. }

LogicProvider 中沒有任何聲明表明它實(shí)現(xiàn)了 Logic 接口。這意味著客戶端將來可以輕松替換其邏輯提供程序,只要該邏輯提供程序包含基礎(chǔ)接口 (Logic) 的所有方法集。

7. 錯(cuò)誤處理

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

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

  1. // the function returns an int and an error
  2. func calculateRemainder(numerator int, denominator int) (int, error) {
  3. // Error returned
  4. if denominator == 0 {
  5. return 9, errors.New("denominator is 0")
  6. }
  7. // No error returned
  8. return numerator / denominator, nil
  9. }

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

8. 并發(fā)

并發(fā)可以說是 Go 最著名的功能,并發(fā)允許在機(jī)器或服務(wù)器上的可用內(nèi)核數(shù)量上并行運(yùn)行任務(wù)。當(dāng)單獨(dú)的進(jìn)程不相互依賴(不需要按順序運(yùn)行)并且時(shí)間性能至關(guān)重要時(shí),并發(fā)性最有意義。I/O 要求通常就是這種情況,其中讀取或?qū)懭氪疟P或網(wǎng)絡(luò)比除最復(fù)雜的內(nèi)存中進(jìn)程之外的所有進(jìn)程慢幾個(gè)數(shù)量級。

函數(shù)調(diào)用之前的 'go' 關(guān)鍵字將開啟并發(fā) goroutine 運(yùn)行該函數(shù)。

  1. func process(val int) int {
  2. // do something with val
  3. }
  4. // for each value in 'in', run the process function concurrently,
  5. // and read the result of process to 'out'
  6. func runConcurrently(in <-chan int, out chan<- int){
  7. go func() {
  8. for val := range in {
  9. result := process(val)
  10. out <- result
  11. }
  12. }
  13. }

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

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

Go 具有"電池包含"的理念,現(xiàn)代編程語言的許多需求都融入了標(biāo)準(zhǔn)庫中,這使得程序員的生活變得更加簡單。

如前所述,Go 是一種相對年輕的語言,這意味著標(biāo)準(zhǔn)庫中滿足了現(xiàn)代應(yīng)用程序的許多問題/需求。

首先,Go 為網(wǎng)絡(luò)(特別是 HTTP/2)和文件管理提供了世界一流的支持。它還提供本地 JSON 編碼和解碼。因此,設(shè)置服務(wù)器來處理 HTTP 請求和返回響應(yīng)(JSON 或其他)非常簡單,這解釋了 Go 在開發(fā)基于 REST 的 HTTP Web 服務(wù)方面的受歡迎程度。

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

10. 調(diào)試:Go Playground

使用任何語言進(jìn)行調(diào)試都是一項(xiàng)關(guān)鍵需求。大多數(shù)語言都依賴于第三方在線工具或聰明的 IDE 來提供調(diào)試工具,使開發(fā)人員能夠快速檢查其代碼。Go 提供了 Go Playground — https://go.dev/play 一個(gè)免費(fèi)的在線工具,你可以在其中試用和共享小程序。這是一個(gè)非常有用的工具,使調(diào)試成為一項(xiàng)簡單的練習(xí)。

沒記錯(cuò)的話,Go 應(yīng)該開啟了 playground 的先河,之后發(fā)布的語言也提供類似的功能,比如 Rust 和 Swift。

總結(jié)

除了以上介紹的 10 個(gè)特性,你認(rèn)為還有其他特性是 Go 獨(dú)特的地方嗎?

參考資料

[1]Robert Griesemer: https://en.wikipedia.org/wiki/Robert_Griesemer

[2]Rob Pike: https://en.wikipedia.org/wiki/Rob_Pike

[3]Ken Thompson: https://en.wikipedia.org/wiki/Ken_Thompson

[4]堆棧: https://en.wikipedia.org/wiki/Stack-based_memory_allocation

[5]堆: https://www.educba.com/what-is-heap-memory/

[6]Google App Engine: https://cloud.google.com/appengine

[7]Maven Central: https://search.maven.org/

[8]NPM: https://www.npmjs.com/

[9]是通過值傳遞: https://itnext.io/the-power-of-functional-programming-in-javascript-cc9797a42b60

[10]指針: https://www.ardanlabs.com/blog/2017/05/language-mechanics-on-stacks-and-pointers.html

[11]總結(jié): http://web.mit.edu/6.031/www/fa20/classes/08-immutability/

[12]這篇文章: https://www.forrestthewoods.com/blog/memory-bandwidth-napkin-math/

[13]knex.js: https://knexjs.org/

[14]Mat Ryer: https://twitter.com/matryer

[15]SOLID: https://en.wikipedia.org/wiki/SOLID

[16]設(shè)計(jì)模式: https://en.wikipedia.org/wiki/Software_design_pattern

[17]Mat Ryer: https://twitter.com/matryer

原文鏈接:https://mp.weixin.qq.com/s/nzm7VaP47Cj2v0nz4GqBfQ

延伸 · 閱讀

精彩推薦
  • GolangGolang中Bit數(shù)組的實(shí)現(xiàn)方式

    Golang中Bit數(shù)組的實(shí)現(xiàn)方式

    這篇文章主要介紹了Golang中Bit數(shù)組的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    天易獨(dú)尊11682021-06-09
  • Golanggolang的httpserver優(yōu)雅重啟方法詳解

    golang的httpserver優(yōu)雅重啟方法詳解

    這篇文章主要給大家介紹了關(guān)于golang的httpserver優(yōu)雅重啟的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,...

    helight2992020-05-14
  • Golanggolang如何使用struct的tag屬性的詳細(xì)介紹

    golang如何使用struct的tag屬性的詳細(xì)介紹

    這篇文章主要介紹了golang如何使用struct的tag屬性的詳細(xì)介紹,從例子說起,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看...

    Go語言中文網(wǎng)11352020-05-21
  • Golanggo日志系統(tǒng)logrus顯示文件和行號的操作

    go日志系統(tǒng)logrus顯示文件和行號的操作

    這篇文章主要介紹了go日志系統(tǒng)logrus顯示文件和行號的操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    SmallQinYan12302021-02-02
  • GolangGolang通脈之?dāng)?shù)據(jù)類型詳情

    Golang通脈之?dāng)?shù)據(jù)類型詳情

    這篇文章主要介紹了Golang通脈之?dāng)?shù)據(jù)類型,在編程語言中標(biāo)識符就是定義的具有某種意義的詞,比如變量名、常量名、函數(shù)名等等,Go語言中標(biāo)識符允許由...

    4272021-11-24
  • Golanggo語言制作端口掃描器

    go語言制作端口掃描器

    本文給大家分享的是使用go語言編寫的TCP端口掃描器,可以選擇IP范圍,掃描的端口,以及多線程,有需要的小伙伴可以參考下。 ...

    腳本之家3642020-04-25
  • Golanggolang json.Marshal 特殊html字符被轉(zhuǎn)義的解決方法

    golang json.Marshal 特殊html字符被轉(zhuǎn)義的解決方法

    今天小編就為大家分享一篇golang json.Marshal 特殊html字符被轉(zhuǎn)義的解決方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧 ...

    李浩的life12792020-05-27
  • Golanggolang 通過ssh代理連接mysql的操作

    golang 通過ssh代理連接mysql的操作

    這篇文章主要介紹了golang 通過ssh代理連接mysql的操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    a165861639710342021-03-08
主站蜘蛛池模板: 男生和老师一起差差差 | 暖暖在线精品日本中文 | 成人影院在线观看视频 | 思敏1一5集国语版免费观看 | asianfemdom妍妍女王 | 欧美影院天天5g天天爽 | 99精品视频一区在线观看miya | 秋霞午夜伦午夜高清福利片 | 999久久久免费精品国产牛牛 | 热国产热综合 | 亚洲AV 中文字幕 国产 欧美 | sss亚洲国产欧美一区二区 | 日韩一区国产二区欧美三 | 天天操天天射天天色 | coolgay男男gayxxx| yellow高清视频日本动漫 | 免费人成网址在线观看国内 | 亚洲国产欧美另类 | 国产资源免费观看 | 啪一啪日一日 | 亚洲香蕉伊在人在线观看9 亚洲系列国产系列 | 国产一成人精品福利网站 | 国产精品成人免费观看 | 女上男下gifxxoo动态视频 | 国产成人高清精品免费5388密 | 天天综合天天色 | 美女黄金大片视频免费看 | 五月婷婷伊人网 | 五月天网站 | 欧美特级特黄a大片免费 | 日韩久久影院 | 成人欧美视频在线看免费 | 日韩久久综合 | haodiaocao的视频这里看 | 国产91精品露脸国语对白 | 精品视频一区二区三区免费 | 日韩欧美高清 | 国产亚洲一级精品久久 | 日本一在线中文字幕天堂 | 1024人成网站色 | 小早川怜子在线播放精品 |