從C++到GO
剛開始接觸Go語言,看了兩本Go語言的書,從c++開發者的角度來看看go語言的新特性,說下自己感觸較深的幾點:
並發編程
Go語言層面支持協程,將並發業務邏輯從異步轉為同步,大幅提高開發效率;
在c++中,做並發編程目前主流的方案是事件驅動(單線程/多線程/多進程模型等),而事件驅動就需要一個IO多路復用的分發器(select/epoll),這樣,就造成了業務邏輯的斷開,在代碼層面為異步模型,比如:
1).先是一段業務代碼
2).調用IO(業務斷裂)
3).IO完成后的后續處理邏輯;
而go中的協程的支持讓這樣的開發工作就輕松多了,按照同步的方式順序寫業務邏輯,遇到IO也沒關系,一個線程中可以創建成上百萬個協程,這個協程阻塞了就跑下一個,不需要應用代碼層面來負責IO后續調度的處理;
比起自己用C/C++去封裝底層或調用libevent之類的庫,Go的優勢是將事件機制封裝成了CSP模式,編程變得方便了,但是需要付出goroutine調度的開銷;
ps1:Go語言標准庫提供的所有系統調用操作(當然也包括所有同步IO 操作),都會出讓CPU 給其他goroutine;
ps2:看過網上的經驗數據,同步和異步的開發效率(不是運行效率,指的是出活速度)差不多是4:1,嘿嘿,這個數據好激動~~
關於事件驅動與協程在處理並發上的對比,詳見不鳥萬Rio的回答:
https://www.zhihu.com/question/19585576/answer/12424447
垃圾回收
毫無疑問這個好用,有了垃圾回收,不需要開發者自行控制內存的釋放,這樣可避免一堆問題(重復釋放、忘記釋放內存、訪問已釋放的內存等);
當然,c++11引入的智能指針(unique_ptr等)如果在程序中應用的普遍,也可以達到類似垃圾回收的目的;
GC帶來的問題也是有的,會造成STW,會有程序停止調度的卡頓;
Go1.5的GC利用各種手段大大縮減了STW的時間。Go語言官方保證,在50毫秒的Go程序運行時間中因GC導致的調度停頓至多只有10毫秒。
(ref:http://www.infoq.com/cn/articles/2015-review-go)
函數多返回值
這在python里算不得什么新鮮事,但對c++來說,要實現函數返回多個數據,要么封裝一個結構體,要不就只能通過函數傳參實現;
多返回值這玩意,在碼字的時候能提升心情愉悅感啊,想想,在要返回多個值的場景,不用再找個地方用一個結構體封裝一下,直接返回,多直接:
func getName()(firstName, middleName, lastName, nickName string){
return "May", "M", "Chen", "Babe"
}
錯誤處理
提到多返回值,就接着說說錯誤處理,估計多返回值應用最多的場景就是第二個參數傳回函數的錯誤狀態;比如以下寫法就很常見了:
if result, ok := moreMagic(); ok {
/ Do something with result /
}
c/c++對錯誤的處理一般都是通過錯誤碼來確定一個函數是否正確調用,因此相比c/c++而言,go的錯誤處理代碼行減少了,看上去也美觀優雅;
go引入了3個關鍵字(defer、panic和
recover)用於標准的錯誤處理流程;defer關鍵字的引入,保證錯誤處理的代碼在發現錯誤時一定能夠被調用,不會因為業務分支邏輯上的修改而漏調;
當然,看和誰比了,python的實踐者認為沒有使用try catch的異常處理機制,讓錯誤處理顯得很繁瑣;
Russ Cox指出Go語言是為大型軟件設計的,Go語言的返回錯誤方式,不可否認,對於調用者不是很方便,但這樣做會讓程序中可能會出錯的地方顯的很明顯。對於小程序來說,你可能只想打印出錯誤,退出程序。對於一些很精密的程序,根據異常的不同,來源的不同,程序會做出不同的反應,這很常見,這種情況中,try + catch的方式相對於錯誤返回模式顯得冗長。
ref:
Go語言的錯誤處理機制引發爭議
http://www.infoq.com/cn/news/2012/11/go-error-handle
函數的地位提升
函數作為“類型”出現,成為了一等公民;可以定義函數類型,將一個函數賦值給函數變量,然后在業務鏈中傳遞,這個在c++中只有使用std::function才能做到;
還可以使用匿名函數(對應c++11中的lambda表達式),在語言層面支持函數編程,從而可以對程序進行更加靈活的控制和管理。
強制的編碼規范
系統做大做久了,代碼質量難免下降;開發人員的代碼風格不一致,導致程序中充斥着千奇百怪的命名及類的組織方式;
是的,是個公司就會有代碼規范,但那只是寫在紙面上的東西,是否真照着執行了,還真不好說;什么后期掃描,不改不給上線?
為工程而生,go強制的編碼規范,讓人耳目一新,從命名、到代碼排列組織方式都有明確的規定,不符合就不能編譯通過!這個真得叫好;代碼工程不是實現個性張揚的地方;
語法后置,為啥這么搞?
以上聊到的都是go的優點,看一個爽一個;但go的語法,如變量、函數的聲明和定義,和我們常見的語言語法相比,都是類型后置,這點着實有些不習慣;
為啥要這么搞?
Rob Pike(go語言的創建者之一)針對這個問題給過解釋:不是為了與眾不同,而是為了更加清晰易懂。特別是當類型比較復雜時,Go的類型語法要比 C 的容易懂。
詳見:
https://www.zhihu.com/question/21656696/answer/19027040
最后,貼幾點Go語言的哲學:
Go語言集眾多編程范式之所長,並以自己獨到的方式將它們融合在一起。程序員們可以用他們喜歡的風格去設計程序。
相對於設計規則上的靈活,Go語言有着明確且近乎嚴格的編碼規范。我們可以通過“go fmt”命令來按照官方的規范格式化代碼。
Go語言是強調軟件工程的編程語言。它自帶了非常豐富的標准命令,涵蓋了軟件生命周期(開發、測試、部署、維護等等)的各個環節。
Go語言是雲計算時代的編程語言。它關注高並發程序,並旨在開發效率和運行效率上取得平衡。
Go語言提倡交換數據,而不是共享數據。它的並發原語Goroutine和Channel是其中的兩大並發編程利器。同時,Go語言也提供了豐富的同步工具,以供程序員們根據場景選用。然而,后者就不屬於語言級別的支持了。
http://www.infoq.com/cn/articles/go-language-introduction
Posted by: 大CC | 26JAN,2016
博客:blog.me115.com [訂閱]
Github:大CC