這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。最近,我在做興趣項目的時候開始探索 Go 語言,被 Go 語言的美征服了。Go語言的美在於它在靈活使用(常見於一些動態,解釋型語言)和安全效能(常見於一些靜態,編譯語言)之間有一個很好的平衡。除此之外,還有另外的兩個功能讓我覺得 Go 語言非常適合現代的軟體開發。我會在之下優勢的部分闡述。其中之一是 **對語言並發性的一流支援**(通過 `goroutine`,和 `channels` 實現,下面解釋)。 並發,通過其設計,使您能夠有效地使用您的 CPU 馬力。 即使您的處理器只有1個核心,並發的設計也能讓您高效地使用該核心。 這就是為什麼您通常可以在單台機器上運行數十萬個並發 `goroutines`(輕量級線程)的原因。 `channels` 和 `goroutines` 是分布式系統的核心,因為它們抽象了生產者 - 消費者的訊息範例。我非常喜歡 Go 的另一個特性是介面 `(Interface)` 。 **介面為您的系統提供松耦合或分離組件。** 這意味著你的代碼的一部分可以只依賴於介面類型,並不關心誰實現了介面或介面是如何?的。 然後,您的控制器可以提供一個滿足介面(實現介面中的所有功能)的代碼的依賴關係。 這也為單元測試提供了一個非常乾淨的架構(通過依賴注入)。 現在,您的控制器可以注入代碼所需的介面的類比實現,以便能夠測試它是否正確地執行其工作。綜上所訴我認為 Go 是一門很棒的語言。 特別是對於像雲系統開發(Web 服務器,CDN,緩衝等),分布式系統,微服務等用例。因此,如果你是一名工程師或初創公司試圖決定你想要探索或嘗試的語言,請認真的考慮一下 Go。在這篇文章中,我將討論該語言的以下幾個方面:a)介紹 b)為什麼需要Go c)目標受眾 d)Go的優勢 e)Go的弱點 f)走向2 g)Go的設計理念 h)如何開始 i)誰在使用Go## 介紹Go 是一款開源語言,由 Robert Griesemer,Rob Pike 和 Ken Thompson 在 Google 建立。開原始碼意味著每個人都可以通過為新功能提供[建議](https://github.com/golang/go/wiki/ExperienceReports),修複錯誤等來為語言做出貢獻。語言的代碼在[GitHub](https://github.com/golang/go)上。 [這裡](https://golang.org/doc/contribute.html)提供了有關如何為語言做出貢獻的文檔。## 為什麼需要 Go作者提到,設計新語言的主要動機是解決 Google 的內部軟體工程問題。 他們還提到 Go 實際上是作為 C++ 的替代品而開發的。Rob Pike 提到 Go 程式設計語言的目的:> “因此,Go 的目的不是研究程式設計語言設計; 它是為了改善設計師和同事的工作環境。 Go 比程式設計語言研究更關注軟體工程。 或者換句話說,就是為軟體工程師服務的語言設計。”**困擾Google軟體工程視野的問題**(摘自(https://talks.golang.org/2012/splash.article)):a)緩慢的構建 - 構建有時需要一個小時才能完成 b)不受控制的依賴 c)每個程式員使用該語言的不同子集 d)程式理解不佳(代碼難以閱讀,記錄不當等等) e)重複努力 f)更新的成本 g)版本歪斜 h)編寫自動工具的難度 i)跨語言構建 **為了成功,Go必須解決這些問題**(摘自(https://talks.golang.org/2012/splash.article)):a)Go必須能大規模的使用,用於多人的大組,並且適用於有大量依賴程式的項目。 b)Go的文法必須是讓人熟悉的,大致類C。 Google需要在Go中快速提高程式員的效率,這意味著語言的文法的變化不能太激進。 c)Go必須是現代的。 它應該具有像並發這樣的功能,以便程式可以高效地使用多核機器。 它應該有內建的網路和Web伺服器庫,以便它有助於現代化的發展。## 目標聽眾Go 是一種系統程式設計語言。 對於諸如雲系統(網路伺服器,緩衝),微服務,分布式系統(由於並發支援)而言,Go 確實非常出色。## 優勢**a)靜態類型:** Go 是靜態類型的。 這意味著您需要在編譯時間為所有變數和函數參數(以及返回變數)宣告類型。 雖然這聽起來不方便,但這有一個很大的優勢,因為在編譯時間本身會發現很多錯誤。 當你的團隊規模增加時,這個因素起著非常重要的作用,因為聲明的類型使得函數和庫更易讀,更容易理解。**b)編譯速度:**Go 代碼編譯速度**非常快**,因此您無需繼續等待代碼編譯。 實際上,`go run` 命令會很快啟動你的Go程式,所以你甚至不會覺得你的代碼是先編譯好的。 這感覺就像一種解釋性語言。**c)執行速度:** 根據作業系統(Linux/Windows/Mac)和代碼正在編譯的機器的 CPU 指令集體繫結構(x86,x86-64,arm等),Go 代碼直接編譯為機器代碼。 所以,它運行速度非常快。**d)攜帶型:** 由於代碼直接編譯為機器碼,因此,二進位檔案變得便攜。 這裡的可移植性意味著你可以從你的機器(比如 Linux,x86-64)擷取二進位檔案並直接在你的伺服器上運行(如果你的伺服器也在 x86-64 架構上運行 Linux)。由於 Go 二進位檔案是靜態連結的,這意味著您的程式需要的任何共用作業系統庫都將在編譯時間包含在二進位檔案中。它們在運行程式時不會動態連結。這對於在資料中心的多台機器上部署程式具有巨大的好處。如果您的資料中心中有 100 台機器,只要將二進位檔案編譯為您的機器所啟動並執行相同作業系統和指令集體繫結構,就可以簡單地將您的程式二進位檔案 “scp” 到所有這些機器。 你不需要關心他們正在啟動並執行 Linux 版本。 不需要檢查/管理依賴關係。 二進位檔案啟動並執行過程中,所有的程式都跑起來了。**e)並發性:** Go 對並發有一流的支援。 並發是 Go 的主要賣點之一。 語言設計師圍繞托尼霍爾的[“Communicating Sequential Processes”](http://www.cs.cmu.edu/~crary/819-f09/Hoare78.pdf)論文設計了並行存取模型。**Go 運行時允許您在機器上運行數十萬個並發 `goroutine` 。**`Goroutine` 是一個輕量級的執行線程。 Go 運行時將這些 `goroutine` 複用到作業系統線程上。 這意味著多個 `goroutine` 可以在單個作業系統線程上同時運行。 Go 運行時有一個發送器,其任務是調度這些 `goroutine` 執行。這種方法有兩個好處:1. 初始化時的 `Goroutine` 具有 2KB 的堆棧。與一個一般為 1 MB 的 OS 線程堆棧相比,這非常小巧。當你需要同時運行幾十萬個不同的 goroutine 時,這個數字很重要。如果你要並行運行數千個 OS 線程,RAM 顯然將成為瓶頸。2. Go 可以遵循與 Java 等其他語言相同的模型,它支援與 OS 線程相同的線程概念。但是在這種情況下,OS 線程之間的環境切換成本比不同的 `goroutine` 之間的環境切換成本要大得多。由於我在本文中多次提及“並發性”,因此我建議您查看 Rob Pike 關於[“並發性不是並行性”](https://www.youtube.com/watch?v=cN_DpYBzKso)的討論。在編程中,並發是獨立執行的進程的組成,而並行則是(可能相關的)計算的同時執行。除非你有一個擁有多個核心的處理器或者擁有多個處理器,否則你不能真正擁有並行性,因為 CPU 核心一次只能執行一件事。在單個核心機器上,只有並發才是幕後工作。 OS 發送器針對處理器上的不同時間片調度不同的進程(實際上線程,每個進程至少有一個主線程)。因此,在某個時刻,您只能在處理器上運行一個線程(進程)。由於指令的執行速度很快,我們感覺到有很多事情正在運行。但實際上這隻是一件事。並發是一次處理很多事情。並行是一次做很多事情。**f)介面:** 介面使鬆散耦合的系統成為可能。 Go 中的介面類型可以被定義為一組函數。而已。任何實現這些函數的類型都會隱式地實現介面,即不需要指定類型實現介面。這由編譯器在編譯時間自動檢查。這意味著你的代碼的一部分可以只依賴於一個介面類型,並不關心誰實現了介面或介面是如何?的。然後你的主/控制器函數可以提供一個滿足介面(實現介面中所有函數)的依賴關係。這也為單元測試提供了一個非常乾淨的架構(通過依賴注入)。現在,您的測試代碼可以注入代碼所需的介面的類比實現,以便能夠測試它是否正確地執行其工作。雖然這對於解耦是非常好的,但另一個好處是您可以開始將您的體繫結構視為不同的微服務。即使您的應用程式駐留在單個伺服器上(如果您剛剛開始),也可以將應用程式中所需的不同功能設計為不同的微服務,每個微服務都實現它承諾的介面。所以其他服務/控制器只是調用介面中的方法,而不是實際關心它們是如何在幕後實現的。**g)垃圾收集:** 與 C 不同,你不需要記住釋放指標或擔心 Go 中懸掛指標。垃圾收集器自動完成這項工作。**h)不報錯異常,自己處理錯誤:** 我喜歡 Go 沒有其他語言具有的標準異常邏輯。去強迫開發人員處理“無法開啟檔案”等基本錯誤,而不是讓他們將所有程式碼封裝裝在 try catch 塊中。這也迫使開發人員考慮需要採取什麼措施來處理這些故障情況。**i)驚人的工具**:關於Go的最好方面之一是它的工具。它有如下工具:i) [Gofmt](https://blog.golang.org/go-fmt-your-code):它會自動格式化和縮排你的代碼,這樣你的代碼看起來就像這個星球上的每個 Go 開發人員一樣。這對代碼可讀性有巨大的影響。ii) [Go run](https://golang.org/cmd/go/#hdr-Compile_and_run_Go_program):編譯你的代碼並運行它們,都是:)。因此,即使 Go 需要編譯,這個工具也讓你覺得它是一種解釋型語言,因為它只是編譯你的代碼的速度非常快,以致於當代碼編譯完成時你甚至不會感覺到它。iii) [Go get](https://golang.org/cmd/go/#hdr-Download_and_install_packages_and_dependencies):從 GitHub 下載庫並將其複製到 GoPath,以便您可以將庫匯入到項目中iv) [Godoc](https://godoc.org/golang.org/x/tools/cmd/godoc):Godoc 解析您的 Go 原始碼 - 包括注釋 - 並以 HTML 或純文字格式產生其文檔。通過 Godoc 的網路介面,您可以看到與其所記錄代碼緊密結合的文檔。只需點擊一下,您就可以從函數的文檔導航到其實現。你可以在這裡查看更多的[工具](https://golang.org/cmd/go/)。**k)優秀的內建庫:** Go 有很棒的內部庫來協助當前的軟體開發。它們之中有一些是:a) [net/http](https://golang.org/pkg/net/http/) - 提供 HTTP 用戶端和伺服器實現b) [database/sql](https://golang.org/pkg/database/sql/) - 用於與 SQL 資料庫互動c) encoding/json - JSON 被視為標準語言的第一類成員 :)d) html/templates - HTML 範本庫e) io/ioutil - 實現 I/O 公用程式功能Go 的開發有很多進展。你可以在[這裡](https://github.com/avelino/awesome-go)找到所有的 Go 庫和架構,用於各種工具和用例。## 弱點**1.泛型的缺乏** - 泛型讓我們在稍後指定待指定的類型時設計演算法。假設您需要編寫一個函數來對整數列表進行排序。稍後,您需要編寫另一個函數來排序字串列表。在那一刻,你意識到代碼幾乎看起來一樣,但你不能使用原始函數,因為函數可以將一個整數類型列表或一個類型字串列表作為參數。這將需要代碼重複。因此,泛型允許您圍繞稍後可以指定的類型設計演算法。您可以設計一個演算法來排序T類型的列表。然後,您可以使用整數/字串/任何其他類型調用相同的函數,因為存在該類型的排序函數。這意味著編譯器可以檢查該類型的一個值是否大於該類型的另一個值(因為這是排序所需的)通過使用語言的空介面 `(interface {})` 功能,可以在 Go 中實現某種通用機制。但是,這並不理想。泛型是一個備受爭議的話題。一些程式員發誓。而其他人不希望它們包含在該語言中,因為泛型通常是編譯時間和執行時間之間的折衷。這就是說,Go 的作者在 Go 中表達了對實施某種泛型機制的開放性。但是,這不僅僅是泛型。泛型只有在語言的所有其他功能都能正常工作時才能實現。讓我們拭目以待 Go 2 是否為他們提供了某種解決方案。**2.缺乏依賴管理** - Go1 的承諾意味著 Go 語言及其庫在 Go 1 的生命週期中不能更改其API。這意味著您的原始碼將繼續為 Go 1.5 和Go 1.9 編譯。因此,大多數第三方 Go 庫也遵循相同的承諾。由於從 GitHub 獲得第三方庫的主要方式是通過 'go get' 工具,因此,當您執行 `go get github.com/vendor/library` 時,您希望他們主分支中的最新代碼不會更改庫 API。雖然這對臨時項目很酷,因為大多數庫沒有違背承諾,但這對於生產部署並不理想。理想情況下應該有一些依賴版本的方法,這樣你就可以簡單地在你的依賴檔案中包含第三方庫的版本號碼。即使他們的 API 改變了,你也不需要擔心,因為新的 API 將帶有更新的版本。您稍後可以回頭查看所做的更改,然後決定是否升級您的依賴檔案中的版本並根據 API 介面中的更改更改您的用戶端代碼。Go 的官方實驗 [dep](https://github.com/golang/dep) 應該很快成為這個問題的解決方案。可能在 Go 2。(譯註:vgo 會解決此問題)## Go 2 的開發我非常喜歡作者採用這種開源方法來實現這種語言。如果你想在 Go 2 中實現一個功能,你需要編寫一個文檔,你需要:a)描述你的用例或問題 b)說明如何使用 Go 無法解決用例/問題 c)描述一個問題究竟有多大(有些問題不夠大或者沒有足夠的重點來解決某個特定時刻的問題)。 d)可能的話,提出如何解決問題的解決方案 作者將對其進行審查並將其連結到[此處](https://github.com/golang/go/wiki/ExperienceReports)。所有關於問題的討論都將在郵件清單和問題跟蹤器等公用媒體上進行。在我看來,語言的兩個最緊迫的問題是泛型和依賴管理。依賴管理更多的是發布工程或工具問題。希望我們會看到 [dep](https://github.com/golang/dep)(官方實驗)成為解決問題的官方工具。鑒於作者已經表達了對該語言的泛型的開放性,我很好奇他們是如何?它們的,因為泛型以編譯時間或執行時間為代價。## Go的設計理念在 Rob Pike 的的 talk [“簡單就是複雜”](https://talks.golang.org/2015/simplicity-is-complicated.slide#18)中,他提到的一些設計理念讓我覺得很有亮點。具體來說,我喜歡的是:a)**傳統上,其他語言都希望不斷添加新功能。**通過這種方式,所有的語言都只是增加了臃腫性,編譯器及其規範中的複雜性過高。如果這種情況持續下去,每種語言將在未來看起來都一樣,因為每種語言都會不斷添加它沒有的功能。考慮一下,JavaScript 添加物件導向的功能。 Go 作者故意沒有在語言中包含很多功能。**只有那些作者達成一致意見的特徵才被包括在內,因為那些真正覺得他們確實為語言所能達到的東西帶來了價值的特徵。**b)**特徵像解空間中的正交向量。** 重要的是能夠為您的用例選擇和組合不同的向量。**而這些載體應該自然而然地相互配合。意味著該語言的每個功能都可以與其他任何可預測的功能一起工作。** 這樣,這些功能集涵蓋整個解決方案空間。實現所有這些非常自然的功能,給語言實現帶來了很多複雜性。但是該語言將複雜性抽象化並為您提供簡單易懂的介面。因此,簡單性就是隱藏複雜性的藝術c)**可讀性的重要性往往被低估。** 可讀性在設計程式設計語言中是最重要的事情之一,因為維護軟體的重要性和成本非常高。過多的功能會影響語言的可讀性。d)**可讀性也意味著可靠性。** 如果一門語言很複雜,你就必須瞭解更多的東西來閱讀和編寫代碼。同樣,要調試它並能夠修複它。這也意味著您的團隊中的新開發人員需要更大的擴充時間,才能讓他們理解語言,直到他們可以為您的程式碼程式庫貢獻力量。## 如何開始您可以下載Go並按照此處的安裝說明進行操作。這裡是開始使用Go的[官方指南](https://tour.golang.org/welcome/1)。[Go by example](https://gobyexample.com/)也是一本好書。如果你想讀一本書,[The Go Programming Language](https://www.amazon.com/Programming-Language-Addison-Wesley-Professional-Computing/dp/013419044)是一個很好的選擇。 它的編寫方式與傳說中的[C 語言白皮書](https://www.amazon.com/Programming-Language-2nd-Brian-Kernighan/dp/0131103628)相似,由[Alan A. A. Donovan](https://www.informit.com/authors/bio/cd7c1e12-138d-4bf9-b609-e12e5a7fa866)和[Brian W. Kernighan](https://en.wikipedia.org/wiki/Brian_Kernighan)撰寫。您可以加入 [Gophers Slack](https://invite.slack.golangbridge.org/) 頻道,與社區合作並參與有關該語言的討論。## 哪些公司在使用 Go[很多公司](https://github.com/golang/go/wiki/GoUsers)已經開始在 Go 上投入很多資金使用 Go。一些有名的大廠包括:Google - [Kubernetes](http://kubernetes.io/),[MySQL 擴充基礎架構](http://vitess.io/),[dl.google.com](https://talks.golang.org/2013/oscon-dl.slide#1)(下載伺服器)BaseCamp - [Go at BaseCamp](https://signalvnoise.com/posts/3897-go-at-basecamp)CloudFlare - [部落格](https://blog.cloudflare.com/go-at-cloudflare/),[ArsTechnica 文章](https://arstechnica.com/information-technology/2013/02/cloudflare-blows-hole-in-laws-of-web-physics-with-go-and-railgun/)CockroachDB - [為什麼 Go 是 CockroachDB 的正確選擇](https://www.cockroachlabs.com/blog/why-go-was-the-right-choice-for-cockroachdb/)CoreOS - [GitHub](https://github.com/coreos/),[部落格](https://blog.gopheracademy.com/birthday-bash-2014/go-at-coreos/)DataDog - [Go at DataDog](https://blog.gopheracademy.com/birthday-bash-2014/go-at-datadog/)DigitalOcean - [讓您的Team Dev開始使用 Go](https://blog.digitalocean.com/get-your-development-team-started-with-go/)Docker - [為什麼我們決定在 Go 中編寫 Docker](https://www.slideshare.net/jpetazzo/docker-and-go-why-did-we-decide-to-write-docker-in-go/)Dropbox - [開源我們的 Go 庫](https://blogs.dropbox.com/tech/2014/07/open-sourcing-our-go-libraries/)Parse - [我們如何將我們的 API 從 Ruby 轉移到 Go 並儲存了我們的理智](http://blog.parse.com/learn/how-we-moved-our-api-from-ruby-to-go-and-saved-our-sanity/)Facebook - [GitHub](https://github.com/facebookgo/)英特爾 - [GitHub](https://github.com/clearcontainers)Iron.IO - [Go after 2 years in Production/](https://www.iron.io/go-after-2-years-in-production/)MalwareBytes - [每分鐘處理 100 萬個請求,使用 golang](http://marcio.io/2015/07/handling-1-million-requests-per-minute-with-golang/)Medium - [How Medium goes Social](https://medium.engineering/how-medium-goes-social-b7dbefa6d413)MongoDB - [Go Agent](https://www.mongodb.com/blog/post/go-agent-go)Mozilla - [GitHub](https://github.com/search?o=desc&q=org%3Amozilla+org%3Amozilla-services+org%3Amozilla-it+language%3AGo&ref=searchresults&s=stars&type=Repositories&utf8=%E2%9C%93)Netflix - [GitHub](https://github.com/Netflix/rend)Pinterest - [GitHub](https://github.com/pinterest?language=go)Segment - [GitHub](https://github.com/segmentio?language=go)SendGrid - [如何說服您的公司與 Golang 一起使用](https://sendgrid.com/blog/convince-company-go-golang/)Shopify - [Twitter](https://twitter.com/burkelibbey/status/312328030670450688)SoundCloud - [進入SoundCloud](https://developers.soundcloud.com/blog/go-at-soundcloud)SourceGraph - [YouTube](https://www.youtube.com/watch?v=-DpKaoPz8l8)Twitter - [每天處理 5 億次會議](https://blog.twitter.com/engineering/en_us/a/2015/handling-five-billion-sessions-a-day-in-real-time.html)Uber - [部落格](https://eng.uber.com/go-geofence/),[GitHub](https://github.com/uber?language=go)
via: https://hackernoon.com/the-beauty-of-go-98057e3f0a7d
作者:Kanishk Dudeja 譯者:wentingrohwer 校對:polaris1119
本文由 GCTT 原創編譯,Go語言中文網 榮譽推出
本文由 GCTT 原創翻譯,Go語言中文網 首發。也想加入譯者行列,為開源做一些自己的貢獻嗎?歡迎加入 GCTT!
翻譯工作和譯文發表僅用於學習和交流目的,翻譯工作遵照 CC-BY-NC-SA 協議規定,如果我們的工作有侵犯到您的權益,請及時聯絡我們。
歡迎遵照 CC-BY-NC-SA 協議規定 轉載,敬請在本文中標註並保留原文/譯文連結和作者/譯者等資訊。
文章僅代表作者的知識和看法,如有不同觀點,請樓下排隊吐槽
855 次點擊