咱們爲何從Python轉到go?

說完了python,如今來講說爲何咱們選擇go。其實除了Python,咱們也有其餘的選擇,Java、PHP、Lua(openresty),但最終咱們選擇了go。java

雖然Java和PHP都是最好的編程語言(你們都這麼爭的),但我更傾向一門更簡單的語言。而openresty,雖然性能強悍,但lua仍然是動態語言,也會碰到前面說的動態語言一些問題。最後,前金山許式偉用的go,前快盤架構師蔥頭也用的go,因此咱們很天然地選擇了go。python

go並非完美,一堆值得咱們吐槽的地方。mysql

  • error,好吧,若是有語言潔癖的同窗可能真的受不了go的語法,尤爲是約定的最後一個返回值是error。項目裏面常常會充斥這樣的代碼:c++

      if _, err := w.Write(data1); err != nil {
          returun err
      }
      if _, err := w.Write(data2); err != nil {
          returun err
      }

    難怪有個梗是對於一個需求,java的程序員在寫配置的時候,go程序員已經寫了大部分代碼,可是當java的程序員寫完的時候,go程序員還在寫err != nil程序員

    這方面,errors-are-values卻是推薦了一個不錯的解決方案。golang

  • 包管理。go的包管理太弱了,只有一個go get,也就是若是不當心更新了一個外部庫,頗有可能就致使現有的代碼編譯不過了。雖然已經有不少開源方案,譬如godep以及如今纔出來的gb等,但畢竟不是官方的。貌似google也是經過vendor機制來管理第三方庫的。但願go 1.5或者以後的版本能好好處理下這個問題。sql

  • GC。java的GC發展20年了,go才這麼點時間,gc鐵定不完善。因此咱們仍然不能爲所欲爲的寫代碼,否則在大請求量下面gc可能會卡頓整個服務。因此有時候,該用對象池,內存池的必定要用,雖然代碼醜了點,但好歹性能上去了。編程

  • 泛型,雖然go有inteface,但泛型的缺失會讓咱們在實現一個功能的時候寫大量的重複代碼,譬如int32和int64類型的sort,咱們得爲分別寫兩套代碼,好冗餘。go 1.4以後有了go generate的支持,但這種的仍然須要本身根據go的AST庫來手動寫相關的parser,難度也挺大的。雖然也有不少開源的generate實現,但畢竟不是官方的。服務器

固然還有不少值得吐槽的地方,就不一一列舉了,可是go仍舊有它的優點。架構

  • 靜態語言,強類型。靜態編譯能幫咱們檢查出來大量的錯誤,go的強類型甚至變態到不支持隱式的類型轉換。雖然寫代碼感受很彆扭,但減小了犯錯的可能。

  • gofmt,應該這是我知道的第一個官方提供統一格式化代碼工具的語言了。有了gofmt,你們的代碼長一個樣了,也就沒有花括號到底放到結尾仍是新開一行這種蛋疼的代碼風格討論了。由於你們的代碼風格同樣,因此看go的代碼很容易。

  • 天生的並行支持,由於goroutine以及channel,用go寫分佈式應用,寫併發程序異常的容易。沒有了蛋疼的callback致使的代碼邏輯割裂,代碼邏輯都是順序的。

  • 性能,go的性能可能趕不上c,c++以及openresty,但真的也挺強悍的。在咱們的項目中,如今單機就部署了一個go的進程,就徹底可以勝任之前200個python進程乾的事情,並且CPU和MEM佔用更低。

  • 運維部署,直接編譯成二進制,扔到服務器上面就成,比python須要安裝一堆的環境那是簡單的太多了。固然,若是有cgo,咱們也須要將對應的動態庫給扔過去。

  • 開發效率,雖然go是靜態語言,但我我的感受開發效率真的挺高,直覺上面跟python不相上下。對於我我的來講,最好的例子就是我用go快速開發了很是多的開源組件,譬如ledisdb,go-mysql等,而這些最開始的版本都是在很短的時間裏面完成的。對於咱們項目來講,咱們也是用go在一個月就重構完成了第一個版本,併發布。

實際項目中一些Go Tips

到如今爲止,咱們幾乎全部的服務端項目都已經轉向go,固然在使用的時候也遇到了一些問題,列出來算是經驗分享吧。

  • godep,咱們使用godep進行第三方庫管理,可是godep我碰到的最大的坑就是build tag問題,若是一個文件有build tag,godep頗有可能就會忽略這個文件。

  • IO deadline,若是能本身在應用層處理的都本身處理,go的deadline內部是timer來控制,但timer內部採用一個array來實現的heap,全局共用一個鎖,若是大併發量,而且timer數量過多,timeout變更太頻繁,很容易就引發性能問題。

  • GC,這個前面也說了,多用內存池,對象池,另外,我還發現,若是對象的生命週期跟goroutine一致,對性能的提高也不錯,也在go的group問過相關問題,你們猜想多是由於一些對象實際上是在goroutine的8k棧上面分配的,因此一塊兒回收沒有額外GC了。

  • Go gob,若是要作RPC服務,gob並非一個很好的選擇,首先就跟python的pickle不通用,而後爲了作不一樣系統的數據傳入,任何包都必須帶上類型的詳細信息,size太大。go裏面如今還沒一套官方的RPC方案,gRPC貌似有上位的可能。

總結

雖然我如今選擇了go,可是並不表示我之後不會嘗試其餘的語言。語言沒有好壞,能幫我解決問題的就是好語言。但至少在很長的一段時間,我都會用go來進行開發。Let’ go!(轉載自http://siddontang.com/2015/05/16/why-python-to-go/)

相關文章
相關標籤/搜索