本文對Go和Python、Erlang做了一些有趣的分析對比,相信大家能從中感受到Go語言的強大和與眾不同。
本文主要是介紹Go,從語言對比分析的角度切入。之所以選擇與Python、Erlang對比,是因為做為高級語言,它們語言特性上有較大的相似性,不過最 主要的原因是這幾個我比較熟悉。 Go的很多語言特性借鑒與它的三個祖先:C,Pascal和CSP。Go的語法、數(shù)據(jù)類型、控制流等繼承于C,Go的包、面對對象等思想來源于Pascal分支, 而Go最大的語言特色,基于管道通信的協(xié)程并發(fā)模型,則借鑒于CSP分支。
Go/Python/Erlang語言特性對比
如《 編程語言與范式 》一文所說,不管語言如何層出不窮,所有語言的設計離不開2個基本面:控制流和數(shù)據(jù)類型。為了提升語言描述能力,語言一般都提供控制抽象和數(shù)據(jù)抽象。本小節(jié)的語言特性對比也從這4個維度入手,詳見下圖( 點擊見大圖 )。
圖中我們可以看出,相比于Python的40個特性,Go只有31個,可以說Go在語言設計上是相當克制的。
比如,它沒有隱式的數(shù)值轉換,沒有構造函數(shù)和 析構函數(shù),沒有運算符重載,沒有默認參數(shù),也沒有繼承,沒有泛型,沒有異常,沒有宏,沒有函數(shù)修飾,更沒有線程局部存儲。
但是Go的特點也很鮮明,比如,它擁有協(xié)程、自動垃圾回收、包管理系統(tǒng)、一等公民的函數(shù)、??臻g管理等。
Go作為靜態(tài)類型語言,保證了Go在運行效率、內存用量、類型安全都要強于Python和Erlang。
Go的數(shù)據(jù)類型也更加豐富,除了支持表、字典等復雜的數(shù)據(jù)結構,還支持指針和接口類型,這是Python和Erlang所沒有的。特別是接口類型特別強大, 它提供了管理類型系統(tǒng)的手段。
而指針類型提供了管理內存的手段,這讓Go進入底層軟件開發(fā)提供了強有力的支持。
Go在面對對象的特性支持上做了很多反思和取舍,它沒有類、虛函數(shù)、繼承、泛型等特性。
Go語言中面向對象編程的核心是組合和方法(function)。
組合很類似于C語言的struct結構體的組合方式,方法類似于Java的接口(Interface),但是使用方法上與對象更加解耦,減少了對對象內部的侵入。
Erlang 則不支持面對對象編程范式,相比而言,Python對面對對象范式的支持最為全面。
在函數(shù)式編程的特性支持上,Erlang作為函數(shù)式語言,支持最為全面。
但是基本的函數(shù)式語言特性,如lambda、高階函數(shù)、curry等,三種語言都支持。 控制流的特性支持上,三種語言都差不多。
Erlang支持尾遞歸優(yōu)化,這給它在函數(shù)式編程上帶來便利。而Go在通過動態(tài)擴展協(xié)程棧的方式來支持深度遞 歸調用。Python則在深度遞歸調用上經(jīng)常被爆棧。 Go和Erlang的并發(fā)模型都來源于CSP,但是Erlang是基于actor和消息傳遞(mailbox)的并發(fā)實現(xiàn),Go是基于goroutine和管道(channel)的并發(fā)實 現(xiàn)。
不管Erlang的actor還是Go的goroutine,都滿足協(xié)程的特點:由編程語言實現(xiàn)和調度,切換在用戶態(tài)完成,創(chuàng)建銷毀開銷很小。
至于Python,其多 線程的切換和調度是基于操作系統(tǒng)實現(xiàn),而且因為GIL的大坑級存在,無法真正做到并行。
而且從筆者的并發(fā)編程體驗上看,Erlang的函數(shù)式編程語法風格和其OTP behavior框架提供的晦澀的回調(callback)使用方法,對大部分的程序員, 如C/C++和Java出身的程序員來說,有一定的入門門檻和挑戰(zhàn)。而被稱為“互聯(lián)網(wǎng)時代的C”的Go,其類C的語法和控制流,以及面對對象的編程范式, 編程體驗則好很多。
Go/Python/Erlang語言語法對比
所有的語言特性都需要有形式化的表示方式,Go、Python、Erlang三種語言語法的詳細對比如下(點擊見完整大圖 第一部分 , 第二部分 , 第三部 分 )。
正如Go語言的設計者之一Rob Pike所說,“軟件的復雜性是乘法級相關的”。
這充分體現(xiàn)在語言關鍵詞(keyword)數(shù)量的控制上,Go的關鍵詞是最少 的,只有25個,而Erlang是27個,Python是31個。
從根本上保證了Go語言的簡單易學。
Go語言將數(shù)據(jù)類型分為四類:基礎類型、復合類型、引用類型和接口類型。
基礎類型包括:整型、浮點型、復數(shù)、字符串和布爾型。
復合數(shù)據(jù)類型有數(shù) 組和結構體。引用類型包括指針、切片、字典、函數(shù)、通道。
其他數(shù)據(jù)類型,如原子(atom)、比特(binary)、元組(tuple)、集合(set)、記錄 (record),Go則沒有支持。
Go對C語言的很多語法特性做了改良,正如Rob Pike在《 Less is Exponentially More 》中提到,Go的“起點: C語言,解決一些明顯的瑕疵、刪除雜 質、增加一些缺少的特性?!?/p>
比如,switch/case的case子程序段默認break跳出,case語句支持數(shù)值范圍、條件判斷語句;所有類型默認初始化為0, 沒有未初始化變量;把類型放在變量后面的聲明語法( 鏈接 ),使復雜聲明更加清晰易懂;沒有頭文件,文件的編譯以包組織,改善封裝能力;用空接 口(interface {})代替void *,提高類型系統(tǒng)能力等等。
Go對函數(shù),方法,接口做了清晰的區(qū)分。
與Erlang類似,Go的函數(shù)作為第一公民。
函數(shù)可以讓我們將一個語句序列打包為一個單元,然后可以從程序中 其它地方多次調用。
函數(shù)和方法的區(qū)別是指有沒有接收器,而不像其他語言那樣是指有沒有返回值。
接口類型具體描述了一系列方法的集合,而空接口 interfac{}表示可以接收任意類型。
接口的這2中使用方式,用面對對象編程范式來類比的話,可以類比于subtypepolymorphism(子類型多態(tài))和ad hoc polymorphism(非參數(shù)多態(tài))。
從圖中示例可以看出,Go的goroutine就是一個函數(shù),以及在堆上為其分配的一個堆棧。所以其系統(tǒng)開銷很小,可以輕松的創(chuàng)建上萬個goroutine,并且 它們并不是被操作系統(tǒng)所調度執(zhí)行。
goroutine只能使用channel來發(fā)送給指定的goroutine請求來查詢更新變量。這也就是Go的口頭禪“不要使用共享 數(shù)據(jù)來通信,使用通信來共享數(shù)據(jù)”。channel支持容量限制和range迭代器。
Go/Python/Erlang語言詞法對比
TDD Go編程示例
本小節(jié)以TDD方式4次重構開發(fā)一個斐波那契算法的方式,來簡單展示Go的特性、語法和使用方式,如Go的單元測試技術,并發(fā)編程、匿名函數(shù)、閉包 等。 首先,看一下TDD最終形成的單元測試文件:
基于遞歸的實現(xiàn)方案:
測試結果:
基于goroutine實現(xiàn)的并發(fā)方案:
測試結果:
基于迭代的實現(xiàn)方案:
測試結果:
基于閉包的實現(xiàn)方案:
測試結果:
-
編程
+關注
關注
88文章
3614瀏覽量
93685 -
Go
+關注
關注
0文章
43瀏覽量
12248 -
python
+關注
關注
56文章
4792瀏覽量
84627 -
erlang
+關注
關注
0文章
16瀏覽量
5742
原文標題:干貨 | Go/Python/Erlang編程語言對比分析及示例
文章出處:【微信號:ZTEdeveloper,微信公眾號:中興開發(fā)者社區(qū)】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論