我為什麼選擇go語言

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

這裡,我並不打算引起語言爭論的口水仗,我並不是什麼大牛,對語言的造詣也不深,只是想通過自己實際的經曆,來說說為什麼我在項目中選擇go。

其他語言的經曆

C++

在接觸go之前,我已經有多年的c++開發經驗。主要用在遊戲服務端引擎開發以及P2P上面,那可是一段痛並快樂的時期,以至於我看到任何的程式釘子問題都覺得可以用c++這把鎚子給敲定。但是對於互連網項目開發來說,除非你的團隊整體的c++技術水平nb,並且有很強的代碼規範,不然真可能是一場災難,更別說我們現有團隊幾乎沒其他人會這玩意了。

本來,我打算在現有項目中的推送系統中使用c++,並用業餘時間寫好了一個網路底層庫libtnet,但後來還是決定打住,因為沒有人能夠協助我開發。令我比較欣慰的是,libtnet有一個遊戲公司在使用,現處於自我裝載階段,即將放出去,我倒是很期待他們的好訊息。

Lua

在做遊戲的過程中,我也學會了lua這門語言,並且還有幸接觸並完善了雲風在Lua 不是 C++中提到的那個恐怖的lua,c++粘合層。

lua真的是一門非常好的語言,效能高,開發快速。不光遊戲公司大量使用,在互連網領域,因為openresty的流行,一些公司(包括我們)也開始在web端使用lua進行開發。(頗為自豪的是還給openresty反饋過幾個bug)

但是,lua因為太短小精悍,功能庫並不多,很多需要自己去實現,而且,寫出高效能,高品質lua代碼也並不是很容易的事情。另外,因為其動態語言的特性,我們也栽了不少坑,這個後續在詳說。

Python

在我來現有的團隊之前,他們就已經使用python進行整個系統的開發,甚至包括用戶端GUI(這對用戶端童鞋當時就是一個災難,後來換成Qt就舒爽了)。

python的好處不必說,從數不清的公司用它進行開發就知道,庫非常豐富,代碼簡潔,開發迅速。

但是,在項目中經過兩年多python開發之後,我們漸漸出現了很多問題:

  • 效能,python的效能是比較偏低的,對於很多效能熱點代碼,通常都會採用其他的方式實現。在我們的項目中,需要對任何API調用進行簽名認證,認證服務我們開始使用的是tornado實現,但很不幸運的是,放到外網並沒有頂住壓力。所以我們引入openresty,將很多高頻操作實現放到openresty實現,終於頂住了。
  • 部署,python的庫因為太豐富了,所以我們的童鞋引入了很多的庫,個人感覺我們的童鞋可沒有造輪子的興趣。有時候發版本的時候,我們會因為忘記安裝一個庫導致程式無法運行。這可能跟我們團隊沒有成熟營運經驗有關,後續通過salt,puppet這種發布工具應該能解決。
  • 品質,通常我們都認為,因為python代碼的簡潔,我們很容易的能寫出高品質的代碼,但是如果沒有好的代碼控制手段,用python也仍然能寫出渣的代碼,我甚至覺得因為其靈活性,可能會更容易寫出爛的代碼。這可以說是我們團隊的教訓。

這裡,我並沒有噴python的意思,它真的是一門好語言,我能夠通過它快速的構建原型,驗證我的想法,而且還一直在使用。只是在項目中,我們的一些疏忽,導致代碼不可控了,到了不得不重構的地步了。

Why GO?

前面說了我的語言經曆,以及項目到了重構地步的原因,但是為什麼會是go呢?我們可以有很多其他的選擇,譬如java,erlang,或者仍然採用python。我覺得有很多因素考量:

  • 靜態,go是一門靜態語言,有著強型別約束,所以我們不太可能出現在python中變數在運行時類型不符(譬如int + string)這樣的runtime error。 在編譯階段就能夠幫我們發現很多問題,不用等到運行時。(當然,這個靜態語言都能做到)

  • 代碼規範,很多人都比較反感go強制的編碼規範,譬如花括弧的位置。但我覺得,就因為強制約定,所以大家寫出來的go代碼樣子都差不多,不用費心再去深究代碼樣式問題。而且我發現,因為規範統一,我很容易就能理解別人寫的代碼。

  • 庫支援,go的庫非常豐富,而且能通過go get非常方便的擷取github,google code上面的第三方庫(品質你自己得擔著了),再不行,用go自己造輪子也是很方便的,而且造的輪子通常都比較穩定。

  • 開發迅速,不得不說,當你習慣用go開發之後,用go開發功能非常的快,相對於靜態語言c++,開發的效率快的沒話說,我覺得比python都不差,而且品質有保證。我們花了不到一個星期進行推送服務核心功能開發,到現在都沒怎麼變動,穩定運行。

  • 部署方便,因為是靜態,只需要build成一個可運行程式就可以了,部署的時候直接扔一個檔案過去,不需要像python那樣安裝太多的依賴庫。

GO特性

go現在的這個樣子,有些人喜歡,有些人不喜歡,我無法知道為啥google那幫人把go設計成這樣,但是我覺得,既然存在,就有道理,我只需要知道什麼該用,什麼不該用就可以了。

gc

GO提供了gc,這對於c++的童鞋來說,極大的減少了在記憶體上面犯錯的機會,只是go的gc這個效率還真的不好恭維,比起java來說,還有很大的提升空間。

所以有時候寫代碼,我們還得根據tuning來提升gc的效率,譬如採用記憶體池的方式來管理大塊的slice分配,採用no copy的方式來進行string,slice的互轉。

不過go1.3貌似gc效能有了很大的改善,這點讓我比較期待。

defer

go的defer其實是一個讓人又愛又恨的東西,對於防止資源流失,defer可是一個很不錯的東西,但是濫用defer可是會讓你面臨很嚴重的記憶體問題,尤其是像下面的代碼:

for {    defer func(){        //do somthing    }}

別以為go會在調用完成defer之後就好好的進行gc回收defer裡面的東西,在我們進行記憶體profile的時候,發現大量的記憶體佔用都是defer引起的。所以使用起來需要特別謹慎。

但我覺得,這個go應該會稍微改善,在go1.3裡面,也有了對defer的最佳化。

error

也許error是一個讓人爭議很大的東西,現代方式的exception那裡去呢?但是我覺得error能夠非常明確的告訴使用者該函數會有錯誤返回,如果使用exception,除非文檔足夠詳細,我還真不知道哪裡就會蹦出一個異常了。

只是,go又提供了類似exception的defer,panic,recover,這是要鬧哪出。

其實這篇文章我覺得已經解釋的很好了,go程式的慣例是對外的API使用error,而內部錯誤處理可以用defer,recover和panic來簡化流程。

其實這倒跟我一貫的編程準則對應,在團隊在用python進行開發的時候,我們都明確要求庫對外提供的API需要使用傳回值來表示錯誤,而在內部可以使用try,catch異常機制。

interface

go提供了interface來進行抽象編程。何謂介面,最通常的例子就是鴨子的故事,“當看到一隻鳥走起來像鴨子、遊泳起來像鴨子、叫起來也像鴨子,那麼這隻鳥就可以被稱為鴨子“。

在go裡面,interface就是一堆方法的集合,如果某個對象實現了這些方法,那麼該對象可以就算是該interface。使用interface,我們可以很方便的實現非侵入式編程,進行模組功能的替換。

對於長時間沉浸c++和python的童鞋來說,一下子要用interface來解決抽象問題,可能會很不適應。但當習慣之後,你會發現,其實interface非常的靈活方便。

寫到後面

在使用的時候,我們需要知道go到底適用在什麼地方,譬如我們現在也就將API服務使用go重構,我們可沒傻到用go去替換openresty。

總之,go是一門很新的語言,國內也已經有很多公司開始吃這個螃蟹,也有成功的例子了,而我們也正開始了這段旅程。

最後在附上以前給公司同事寫的一個ppt:https://qing.wps.cn/l/b76667b40bdb4b7c91f2b3920a7f4780

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.