go是解釋型語言。 Go(又稱Golang)是Google開發的靜態強型別、編譯型、且髮型,並具有垃圾回收功能的程式語言。 go語言的優勢:學習曲線容易,開發效率和運作效率高,強大的標準函式庫,語言層次定義原始碼的格式化等。
本教學操作環境:windows10系統、GO 1.18、thinkpad t480電腦。
Go(又稱 Golang)是 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 所發展的靜態強型別、編譯型語言。
Go的語法接近C語言,但對於變數的宣告有所不同。 Go支援垃圾回收功能。 Go的平行模型是以東尼·霍爾的通訊順序進程(CSP)為基礎,採取類似模型的其他語言包括Occam和Limbo,但它也具有Pi運算的特徵,例如通道傳輸。在1.8版本中開放插件(Plugin)的支持,這意味著現在能從Go中動態載入部分函數。
與C 相比,Go不包括如枚舉、異常處理、繼承、泛型、斷言、虛函數等功能,但增加了切片(Slice) 型、並發、管道、垃圾回收、介面(Interface)等特性的語言級支援。 Go 2.0版本將支援泛型,對於斷言的存在,則持負面態度,同時也為自己不提供類型繼承來辯護。
不同於Java,Go內嵌了關聯陣列(也稱為雜湊表(Hashes)或字典(Dictionaries)),就像字串類型一樣。
Go語言的優點
#Go 很容易學習
這是事實:如果你了解任何一種程式語言,那麼透過在「Go 語言之旅」學習幾個小時就能夠掌握Go 的大部分語法,並在幾天后寫出你的第一個真正的程式。閱讀並理解 實效 Go 編程,瀏覽一下“包文檔”,玩一玩 Gorilla 或 Go Kit 這樣的網絡工具包,然後你將成為一個相當不錯的 Go 開發者。
這是因為 Go 的首要目標是簡單。當我開始學習 Go,它讓我想起我第一次 發現 Java:一個簡單的語言和一個豐富但不臃腫的標準庫。對比當前 Java 沉重的環境,學習 Go 是一個耳目一新的體驗。因為 Go 的簡易性,Go 程式可讀性非常高,雖然錯誤處理添加了一些麻煩(更多的內容在下面)。
Go 語言的簡單可能是錯誤的。引用 Rob Pike 的話,簡單既是複雜,我們會看到簡單背後有很多的陷阱等著我們去踩,極簡主義會讓我們違背 DRY(Don't Repeat Yourself) 原則。
基於 goroutines 和 channels 的簡單並發程式設計
Goroutines 可能是 Go 的最佳特性了。它們是輕量級的運算線程,與作業系統線程截然不同。
當 Go 程式執行看似阻塞 I/O 的操作時,實際上 Go 運行時掛起了 goroutine ,當一個事件指示某個結果可用時恢復它。同時,其他的 goroutines 已被安排執行。因此在同步程式設計模型下,我們具有了非同步程式設計的可擴展性優勢。
Goroutines 也是輕量級的:它們的堆疊 隨需求增長和收縮,這意味著有 100 個甚至 1000 個 goroutines 都不是問題。
我以前的應用程式中有一個 goroutine 漏洞:這些 goroutines 結束之前正在等待一個 channel 關閉,而這個 channel 永遠不會關閉(一個常見的死鎖問題)。這個進程毫無理由吃掉了 90 % 的 CPU ,而檢查 expvars 顯示有 600 k 空閒的 goroutines! 我猜 goroutine 調度程式佔用了 CPU。
當然,像Akka 這樣的Actor 系統可以輕鬆處理數百萬的Actors,部分原因是actors 沒有堆疊,但是他們遠沒有像goroutines 那樣簡單地編寫大量並發的請求/響應應用程式(即http APIs)。
channel 是 goroutines 的溝通方式:它們提供了一個便利的程式設計模型,可以在 goroutines 之間發送和接收數據,而不必依賴脆弱的低階同步基本體。 channels 有它們自己的一套 用法 模式。
但是,channels 必須仔細考慮,因為錯誤大小的 channels (預設沒有緩衝) 會導致死鎖。下面我們也將看到,使用通道並不能阻止競爭情況,因為它缺乏不可變性。
豐富的標準函式庫
Go 的標準函式庫非常豐富,特別是對於所有與網路協定或API 開發相關的: http 客戶端和伺服器,加密,檔案格式,壓縮,發送電子郵件等等。甚至還有一個html解析器和相當強大的模板引擎去產生 text & html,它會自動過濾 XSS 攻擊(例如在 Hugo 中的使用)。
各種 APIs 一般都簡單易懂。它們有時看起來過於簡單:這個某種程度上是因為 goroutine 程式設計模型意味著我們只需要關心「看似同步」的操作。這也是因為一些通用的函數也可以取代許多專門的函數,就像 我最近發現的關於時間計算的問題。
Go 效能優越
Go 編譯為本機執行檔。許多 Go 的使用者來自 Python、Ruby 或 Node.js。對他們來說,這是一種令人興奮的體驗,因為他們看到伺服器可以處理的並發請求數量大幅增加。當您使用非並發(Node.js)或全域解釋器鎖定的解釋型語言時,這實際上是相當正常的。結合語言的簡易性,這解釋了 Go 令人興奮的原因。
然而與 Java 相比,在 原始效能基準測試 中,情況並不是那麼清晰。 Go 打敗 Java 地方是記憶體使用和垃圾回收。
Go 的垃圾回收器的設計目的是 優先考慮延遲,並避免停機,這在伺服器中尤其重要。這可能會帶來更高的 CPU 成本,但是在水平可伸縮的體系結構中,這很容易透過增加更多的機器來解決。請記住,Go 是由谷歌設計的,他們從不會在資源上短缺。
與 Java 相比,Go 的垃圾回收器(GC)需要做的更少:切片是一個連續的陣列結構,而不是像 Java 那樣的指標陣列。類似地,Go maps 也使用小數組作為 buckets,以達到相同的目的。這意味著垃圾回收器的工作量減少,而且 CPU 快取本地化也更好。
Go 同樣在命令列實用程式中優於 Java :作為本地可執行文件,Go 程式沒有啟動消耗,反之 Java 首先需要載入和編譯的字節碼。
語言層面定義原始碼的格式化
我職業生涯中一些最激烈的辯論發生在團隊程式碼格式的定義上。 Go 透過為程式碼定義規範格式來解決這個問題。 gofmt 工具會重新格式化您的程式碼,並且沒有選項。
不管你喜歡與否,gofmt 定義瞭如何對程式碼進行格式化,一次解決了這個問題。
標準化的測試框架
Go 在其標準函式庫中提供了一個很好的測試框架。它支援並行測試、基準測試,並包含許多實用程序,可以輕鬆測試網路用戶端和伺服器。
Go 程式方便操作
與 Python,Ruby 或 Node.js 相比,必須安裝單一執行檔對於維運工程師來說是一個夢想。隨著越來越多的 Docker 的使用,這個問題越來越少,但獨立的可執行檔也意味著小型的 Docker 映像。
Go還具有一些內建的觀察性功能,可以使用 expvar 套件發佈內部狀態和指標,並且易於添加新內容。但要小心,因為它們在預設的 http 請求處理程序中 自動公開,不受保護。 Java 有類似的 JMX ,但它要複雜得多。
Defer 聲明,防止忘記清理
defer 語句的目的類似於Java 的finally:在目前函數的末尾執行一些清理程式碼,而不管此函數如何退出。 defer 有趣的地方在於它跟程式碼區塊沒有聯繫,可以隨時出現。這使得清理程式碼盡可能接近需要清理的程式碼:
file, err := os.Open(fileName) if err != nil { return } defer file.Close() // 用文件资源的时候,我们再也不需要考虑何时关闭它
當然,Java的試用資源沒那麼冗長,而且Rust 在其所有者被刪除時會自動聲明資源,但是由於Go 要求您清楚地了解資源清理情況,因此讓它接近資源分配很不錯。
新類型
我喜歡類型,因為有些事情讓我感到惱火和害怕,舉個例子,我們到處把持久物件標識符當做string 或long 類型傳遞使用。我們通常會在參數名稱中對 id 的類型進行編碼,但是當函數具有多個標識符作為參數並且某些調用不匹配參數順序時,會造成細微的錯誤。
Go 對新類型有一等支持,即類型為現有類型並賦予其獨立身份,與原始類型不同。與包裝相反,新類型沒有運行時間開銷。這允許編譯器捕捉這種錯誤:
type UserId string // <-- new type type ProductId string func AddProduct(userId UserId, productId ProductId) {} func main() { userId := UserId("some-user-id") productId := ProductId("some-product-id") // 正确的顺序: 没有问题 AddProduct(userId, productId) // 错误的顺序:将会编译错误 AddProduct(productId, userId) // 编译错误: // AddProduct 不能用 productId(type ProductId) 作为 type UserId的参数 // Addproduct 不能用 userId(type UserId) 作为type ProfuctId 的参数 }
不幸的是,缺乏泛型使得使用新類型變得麻煩,因為為它們編寫可重複使用程式碼需要從原始類型轉換值。
更多程式相關知識,請造訪:程式設計影片! !
以上是go是解釋型語言嗎的詳細內容。更多資訊請關注PHP中文網其他相關文章!