12.23 想學習一種新的編程語言嗎?選擇Go吧

快速的運行時,高效的併發性以及簡單易學的語法是最誘人的功能。

想學習一種新的編程語言嗎?選擇Go吧

The Gopher Mascot.

我對學習Go這麼容易感到驚訝。

剛開始學習Go時,我開始從事一個個人項目,這迫使我不得不掌握新的語法(在學習新語言時,我總是想出一個項目)。

我決定創建一個枚舉子域的命令行應用程序,以幫助發現漏洞賞金計劃的資產。 因此,類似於gobuster,它必須並行發出多個HTTP請求,但我想通過一些附加功能(例如,爬取HTML響應以獲取有趣的與安全相關的信息)來重新設計特定的車輪。

我想使用Go-routines解決這個問題。 考慮到發出的HTTP請求數量未知,這將是一個挑戰,因此需要學習如何有效地處理它們。

第一印象

立刻,我發現語法非常陌生,即使我以前從未閱讀過該文檔。 這些概念對我來說似乎很直觀(其他人可能會不同意)。 使用defer很有意義。 用於格式化字符串的fmt軟件包似乎解決了我不知道的問題。 我開始看到Go作為另一種編程語言的開發意圖。 因此,我決定更深入地研究Go,以確定它是否值得花時間學習。

為什麼要開發Go

目的

Go由Google開發,旨在使多處理的開發更加高效和安全,從而隨著時間的推移提高服務器軟件的可維護性,可靠性和有效性。 對於Google而言,這是對他們痛苦的冗長編譯時間所面臨的問題的解答,以及圍繞大規模數據處理的問題的答案,這是當今生產中最普遍的用途之一。 他們想要一種專注於可伸縮性,可讀性和併發性的語言。 它是由於對其他語言的失望和沮喪而誕生的。 他們從現有語言中獲得了最理想的概念,並嘗試對其進行改進並將其結合起來以形成Go。 例如fmt軟件包,這是一個用於處理字符串的高效庫:

"軟件包fmt使用與C的printf和scanf類似的功能實現格式化的I / O。 格式"動詞"源自C,但更簡單。"

這是從成功且流行的語言(在本例中為C)中獲取功能並對其進行改進的示例。

Go的併發是基於CSP建模的; 使用通道,避免共享數據的同步。 他們認為這將是一種更簡單,更安全的通信方式。

另一個重點是簡單性。 需要一種自覺的代碼風格,它是Go社區形成的,具有公認的go風格。 在整個項目中保持一致的方法之一,這將減少在開發過程中配置lint規則和學習不同的代碼風格方法所花費的時間; 團隊合作中的一個重要因素。

從理論上講,這將減少開發人員之間在代碼樣式和方法方面的差異,就像JavaScript這樣的語言(許多Eslint規則)一樣。

方法

所採用的方法將解釋型動態類型語言的編程簡便性與靜態類型編譯語言的效率和安全性相結合。 它具有基本類型,如int,byte和帶有內置map的string。 有指針。 正交性原理是在Go的開發中很重要的原理,並且是函數方法的基礎。

Go使用結構(struct)表示數據,並使用interface表示抽象。 關於Go是否是面向對象的,一直存在爭論。 如果您是Java開發人員,則一開始就很難看到參數的面向對象方面。 難以在Go中查看面向對象的原因可能是因為您正在尋找類型層次結構,而在Go中卻沒有類型層次結構。 有些結構不能繼承,但確實符合對象樣式。 Go只喜歡組合而不是繼承。 您可以通過接受接口來實現多態。 接口被滿足該接口的任何類型的對象所接受。

除了這些核心概念,Go還意識到了由於多核處理而導致的現代併發需求。 強大的併發以goroutine和通道的形式出現。 在大型併發程序中,自動垃圾回收作為有效的內存管理也很重要。 就像使用前綴_test.go一樣簡單地進行單元測試,該前綴在與源文件相同的目錄中聲明。

我為什麼要學習它?

併發

在Go中,併發已根深蒂固。 它是一等公民,就像使用go關鍵字為函數添加前綴一樣容易。 Goroutines是廉價,輕量的執行線程。 在Go中實現併發非常容易。 使用go關鍵字將產生一個新線程,該線程在一組線程的多個內核之間共享。 Goroutine僅有幾千字節,由Go運行時處理,Go運行時將go例程移到不同的可運行線程上,以避免被阻塞。 這使得執行異步和快速。 幾乎與C / C ++一樣快。 您可以使用通道來控制goroutine的數量,儘管它們具有同步感覺,但它們是異步的。

Go的運行時使用可調整大小的有界堆棧,從而使堆棧變小。 運行時會更改內存大小以自動存儲堆棧。 數十萬個goroutine可以在同一地址空間中運行。

簡單

go語言是採用簡約方法開發的。 沒有類或繼承。 這些流行功能(例如Java和Python)中的功能已被結構替換。 Go是強類型和靜態類型的。 鼓勵使用接口,並且無處不在。 靜態類型化的目的是減少編譯時錯誤。 它還使學習變得更容易。

在其他語言(例如JavaScript)中,您會陷入多種觀點,方法和約定之間,而Go卻是一種被普遍接受的樣式指南。 這樣可以更輕鬆地對團隊代碼進行分析和推理,並使集成更加順暢。

儘管沒有隱式轉換,但是語法開銷仍然非常小。 它產生更易讀,更簡單的代碼。

快速

編譯器是靜態鏈接的。 這樣就可以通過編譯生成二進制可執行文件,而無需處理外部依賴項。 儘管增大了體積,但可執行二進制文件已被編譯為本機代碼,而無需使用虛擬機,它使二進制程序更快,更可移植。

另外,Go的其他快速方面是:如上所述的編譯時間和生產時間。 藉助Go,開發人員的工作效率得到了關注,這主要是因為其簡單性。 這樣可以更快地從最初的概念/想法過渡到生產。

它有什麼問題了?

沒有泛型

這是值得商量的。 使用泛型是Java之類的語言,可在確保類型安全的同時提高代碼的可重用性。 go社區提出了這個"問題",並已予以考慮。 您可以在此處遵循建議。 但是,他們目前的立場是,泛型的好處不會超過簡單性和可讀性的好處(沒有泛型)。

競爭條件 Race conditions

"不要通過共享內存進行交流; 而是通過交流共享內存"

這種口頭禪帶來的好處也使Go容易受到競爭條件的影響。

由於go結構的可變性(並且缺少不變的數據結構),您被迫跨多個併發進程共享可變數據。 這樣的一個示例是在沒有深層複製的情況下沿通道發送指針,並且本質上可變的性質為競爭條件打開了大門。 通道可以改善併發編程,但是存在競爭條件的實際風險,其中通道無濟於事。

但是,Go CLI中內置了一個競爭條件檢測器,以幫助檢測競爭條件。

錯誤檢查

檢查錯誤非常明確。 沒有try ... catch語句。 在錯誤處理方面,您必須改變方法和思維方式。 特別是如果您習慣於其他語言。 他們認為,缺少異常可以防止堆積代碼並使返回值過載。 這與其對簡單性的需求聯繫在一起。 您可以在異常情況下緊急處理異常並進行恢復。 還有一種規範的錯誤接口類型,該類型返回帶有Error()的錯誤字符串。

Go開發人員通過使用多值返回檢查錯誤值來處理錯誤。 您可以從預定的能夠產生錯誤的函數中返回錯誤。 通常使用err!= nil將汙染您的代碼庫。

太簡單了一些?

這種簡單性是有代價的。 Go不如JavaScript富有表現力。 沒有默認值。 缺少抽象和泛型使得實現DRY原理變得更加困難,更加複雜,更加不直觀。

要記住的重要一點是Go還很年輕。 正在考慮使用泛型,並且隨著Go的成熟,他們表示仍有考慮的空間。 社區非常努力地不斷開發和改進語言。 就像任何一種語言一樣,Go也有其長處和短處。 我敢肯定,如果足夠多的Gophers(Go程序員)覺得需要某種語言功能,那麼它將得以實現。

但是,儘管看起來某些功能似乎缺失了,但是有時它需要從另一個角度來看待它,以瞭解如何在Go中實現它。

通常,可以通過不同的方法(更友好的Go方式)來實現同一件事。

什麼時候使用

可以肯定地說,在此階段,Go並不能解決所有問題。 特別是與需要大量抽象的GUI和複雜系統有關。

但是,哪種語言可以解決所有問題?

使用轉到它的優點。 如果您認為該語言過於簡單,並且發現很難以一種乾淨的方式增加複雜性,請使用它來構建簡單的微服務而不是複雜的系統。 使用Go構建網絡工具和系統工具,而不是替換更適合當前任務的語言。

因此,最重要的是,使用正確的工具完成工作。 如果該工具是Go,那應該是因為解決該問題是Go擅長的。

所以開始吧。

我想聽聽您對Go的看法; 無論是您使用的產品,感興趣的產品還是有強烈的見解的產品。

(本文翻譯自Lewis Fairweather的文章《Want to Learn a New Programming Language? Consider Go (Golang).》,參考:https://medium.com/swlh/want-to-learn-a-new-programming-language-consider-go-golang-1c32dc3788ba)


分享到:


相關文章: