歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Go語言使用心得

Go語言使用心得

日期:2017/3/1 9:31:47   编辑:Linux編程

13年上半年接觸了Golang,對Golang十分喜愛。現在是2015年,離春節還有幾天,從開始學習到現在的一年半時間裡,前前後後也用Golang寫了些代碼,其中包括業余時間的,也有產品項目中的。一直有想法寫點Golang相關的總結或者感想,決定還是在年前總結下吧。注明下:我只是Golang的喜好者,不是腦殘粉,也無意去挑起什麼語言之爭。

特性少,語法簡單。GO是崇尚極簡主義的,提倡少即是多。這點在它的Spec上尤其凸顯,一下午的時間絕對可以看完。GO的特性很少,很多GO的使用者都反饋,GO的關鍵字至少完全可以記在大腦裡。同時它的語法極為簡單,而且語義清晰。

部署方便。GO是一個強類型靜態語言,可以把代碼編譯為本地機器指令。它的RUNTIME是會在編譯時一起鏈接到執行文件中,這也就意味著我們不需要像JAVA那樣裝一個JVM。而且編譯出的執行文件本身不依賴於其他動態庫,完全可以做到輕松的發布。當然,如果你用GO編寫了調用一些動態庫接口的代碼,那麼還是需要根據實際情況來部署這個動態庫的。這點在很多從python/java轉到go的朋友來說,非常喜歡。

有較完善的標准庫並且較為健壯。GO自身帶的標准庫是比較全面的,從文件歸檔、壓縮、加密、數據庫到數據序列化,字符格式化、校驗和以及網絡庫、同步庫等應有盡有。基本上能夠滿足很多基本的需求了。更好的是,這些標准庫的質量都非常高,都很健壯。接口也較為簡單,有清晰的文檔說明。同時隨著這兩年的發展,GO的第三方庫也多了起來,雖然可能沒有像python那麼多,但是較其發展時間來說,還是非常不錯的。

集成測框架。在之前用C++寫代碼時,寫單元測試不是個容易的工作。需要一些技巧和努力才可以做起來。但是在GO中集成了單元測試框架,只要源碼文件以_test.go結尾,就可以直接通過go test執行單元測試。同時還提供了代碼測試覆蓋率工具,可以很容易實施自動化測試。除此之外,還集成了基准測試框架功能,可以很容易的測量自己寫的函數的運行效率。另外,還有性能剖析器,可以在運行時,測試時剖析程序的瓶頸點,進而可以進行優化。

健全的代碼風格與檢查工具。當初學GO的時候,很多文章和書都會提到go fmt這個命令,統一了代碼風格。我覺著這點實在是解決了風格之爭了。帶來的影響就是別人寫的代碼感覺也是自己寫的一樣。還有golint,可以按照go team的風格和要求來寫代碼。還有go vet可以用來檢查一些在GO中很隱蔽的坑。

簡單卻強大的包管理。GO的包管理可能在很多其他語言的包管理看來太弱了,但是在我看來,它解決了我需要的兩個問題,一個是循環依賴問題,GO是拒絕有循環依賴關系的包;二是包的初始化,每個包的文件都可以實現一個init函數,用來在導入時執行。這點在分工合作時非常有用。

容易編寫跨平台代碼。如果你用純GO,不牽扯到CGO的話,你可以非常容易的做到跨平台。只需要在文件後綴.go前,引入_linux,_windows,_x86,_x64等字符為文件名前綴的結尾就可以做到只在對應的平台中編譯。GO還有build constraints控制代碼在什麼條件下編譯。如果你用到了CGO,就牽扯到了C的跨平台問題,所以稍微麻煩那麼一些,但是問題也不是太大。

垃圾回收。GC的存在極大的降低了並發代碼的編寫,而且還提供了程序的健壯性。做為一個從C/C++做起,有過驅動開發經驗的程序員來說,GC這個東西是我一直沒有涉獵過的。對我來說GC就等於噩夢。但是當我開始試著接受GC時發現,GC真的是解決了程序員的生產力,極大的提高了效率。雖然目前來說GO已經1.4版本了,但是GC還算不得上優秀,按照GO的路線圖,後面會有更優秀的GC實現添加進來。

接口與struct。在第一次學習GO的interface的時候,我第一反應是這就是我想要的。雖然很多人也在說GO的這個interface的不好,而且說的很有道理,比如老趙的《為什麼我不喜歡GO語言式的接口》。interface可以通過組合擴展為新的interface,struct也可以通過組合擴展為新的struct。沒有繼承,只有組合。可以通過匿名組合達到類似繼承的效果。可以對interface進行查詢,有點類似COM的味道,但是語法層面上更為簡單。struct到interface的映射是隱式的,不需要聲明某個struct實現了某個interface。雖然可能會出現名字上的沖突,但是可以通過wrapper進行解決。這種interface的另外一個好處是單元測試時很容易實現MOCK,這點非常喜歡。也可以看這篇文章《Go interfaces make test stubbing easy》

統一的工作布局。GO定義了項目的目錄結構,比如bin目錄,pkg目錄以及src目錄。這個和我日常的項目布局是一致的。之前用C++開發時我們也是如此安排布局,所以就這點來說,我覺著容易過渡。

內建的並發原語。提到GO就不得不提到goroutine和channel。廉價的goroutine可以讓我們歡快的處理異步任務,channel可以用來交換數據。借助goroutine,可以很容易的實現高性能的服務端。goroutine及其調度器可以很容易和EPOLL,IOCP等系統機制結合起來,再通過Half Sync/Half Async模式,很容易在語法層面上達到同步形式,卻不失性能。

2013年初的時候還在做一個客戶端,當時使用了C++0x,其中印象最深的事情是lambad,std::function/bind,結合著線程+隊列的方式,可以很容易的實現類似於Chromuim的線程模型。在處理UI與慢任務比如讀文件,請求網絡數據等交互時,為了保證UI的體驗,使這些任務異步化是非常有必要的。如果有對Golang了解或熟悉的朋友就會明白,這是類似與Golang的goroutine+channel。但是在使用這個模型時,覺著還是繁瑣了些,我要注意對象的生命周期,這個在C++雖然有各種智能指針的幫助,但是難免還會掛一漏萬。而且遇到稍微的復雜的問題,比如一個慢任務接著一個慢任務時,就會涉及到一個任務鏈,在沒有future/promise(Facebook開源的folly庫中有個不錯的實現futures,後來還發現WINDOWS有個基於actor model的並發庫Asynchronous Agents Library非常不錯,只可惜目前只在WINDOWS上使用。)機制的幫助下很容易進入Callback Hell。這樣就會導致代碼相對來說比較難維護,而且容易滋生BUG。好在當時這個部分的代碼不是太多,而且也不是太過於復雜,很容易通過自測穩定下來。

上面雖然提到future/promise, AAL可以解決部分Callback Hell的問題,但是像future還是要用到callback。所以我在想,如果可以做到代碼層面上是同步式的,背後卻是異步的就爽了。GO就滿足了我這個需求。

GO標准庫中還提供了sync包,其中有基本的mutex說,還有RMutex這樣的讀寫鎖,還有Once,WaiterGroup等東西。基本滿足日常中對鎖的需求了。

GO為了幫助程序員解決在並發時經常遇到的race condition問題,還提供了相應的race condition工具。還有相應的死鎖檢測工具。

雖然GO社區有個slogan:”do not communicate by sharing memory; instead, share memory by communicating.“,但是每個goroutine之間並不是完全獨立的,一樣可以做到通過內存共享數據。這個時候只能依靠程序員自己去遵守了。而且因為goroutine不是完全獨立,panic這種東西就可能會導致整個程序掛掉。這點和Erlang比起來確實不是很好。

蛋疼的defer。用習慣了C++的RAII後,十分反感GO的defer機制,但是有的時候又不得不用。原因就是這個defer不是block級別的,而是函數級別的,需要在函數返回前才得到執行。所以這就會導致在處理一些類似於文件打開,操作再關閉的邏輯時非常蛋疼,回到了C的年代,必須手動去Close。

蛋疼的panic。雖然我在C++下不怎麼用異常,但是對於panic這個設計我表示非常的不滿意啊。因為它會影響全局。而要捕捉panic就需要用defer。如果panic只是讓當前goroutine掛掉我覺著就嗨皮壞了。

沒有泛型。GO沒有泛型帶來的蛋疼地方是,要麼就用interface{}來做運行時泛型,要麼就自己手動寫代碼生成器。比如我自己為了生成網絡協議序列化代碼就撸了一個生成器。而且因為沒有泛型,想實現類似C++ STL的容器與算法基本沒太可能,當然方法還是有的,繼續使用代碼生成器。而且GO1.4干脆引入了一個叫go generate的命令。

總結

GO裡面其他一些內建的數據結構,比如slice,map等,但這些也是诟病,因為它又沒給予程序員可以享用range關鍵字的福利。

在GO的所有特性裡,最喜歡就是GC,goroutine,channel以及interface。而其余的特性(比如上面我列舉的很多特性)我覺著都不是太重要,其中很多都可以在工程中實踐,和語言本身沒有太大關系。

總結下來,這東西就是一個工程工具,各種好用,但是從設計角度講各種粗糙,沒必要過度高估。它算的上工程實踐中的好朋友。在寫服務端時,它是把利器,至少在寫服務端程序時,我自己感覺如此。

有朋友說一個語言好不好就看它有沒有開拓你的眼界,給予你新的思想,我想至少GO在這點上滿足了。

Linux系統入門學習-在Linux中安裝Go語言 http://www.linuxidc.com/Linux/2015-02/113159.htm

Ubuntu 安裝Go語言包 http://www.linuxidc.com/Linux/2013-05/85171.htm

《Go語言編程》高清完整版電子書 http://www.linuxidc.com/Linux/2013-05/84709.htm

Go語言並行之美 -- 超越 “Hello World” http://www.linuxidc.com/Linux/2013-05/83697.htm

我為什麼喜歡Go語言 http://www.linuxidc.com/Linux/2013-05/84060.htm

Go語言內存分配器的實現 http://www.linuxidc.com/Linux/2014-01/94766.htm

Copyright © Linux教程網 All Rights Reserved