Python 開發者在遷移到 Go(lang) 時需要知道哪些事?
【編者按】本文最早由 Repustate 釋出,主要介紹將程式碼遷移至 Go(lang) 時的注意事項。文章系國內 ITOM 管理平臺 OneAPM 編譯呈現,以下為正文。
這是一篇講述將大塊 Python/Cython 程式碼遷移到 Go 的長文章。如果你想了解整個事情的經過、背景等所有資訊,請讀下去。如果你只對 Python 開發者需要了解的事感興趣,請下拉到早該知道的事板塊。
背景
我們在 Repustate 最大的技術成果就是實現了阿拉伯語情感分析。阿拉伯語是個難啃的硬骨頭,因為阿拉伯語詞彙的形式非常複雜。阿拉伯語的標記化(把一句話拆分成單個單詞)也比英語要難得多,因為阿拉伯單詞內部可能會包含空格(例如單詞內部“aleph”的位置)。在不洩露機密的情況下,Repustate 利用支援向量機(SVM)來獲取一個句子最可能的意思,並且以此來推斷句子的情感。我們一共採用了22種模型(22個支援向量機),文件中的每個詞都會被分析。也就是說,如果一個文件包含500個詞,就會與支援向量機進行10000多次對比。
Python
Repustate 幾乎完全是用 Python 搭建的,我們使用 Django 來搭建 API 介面和網站架構。因此,為了保持程式碼一致性,使用 Python 來實現所有阿拉伯語情感引擎才說得通。就原型設計和實現流程而言,Python 依然是一個很好的選擇:表現能力優秀,又有強大的第三方庫資源,等等。如果是服務於網頁,它就是最佳選擇。如果是稍低階別的運算,需要與雜湊表(Python 中的字典)進行大量對比時,執行速度就會慢下來。我們一秒鐘只能處理2到3個阿拉伯語單詞,這種速度太慢了。相比之下,我們的英語情感引擎每秒能處理500個單詞。
瓶頸
因此,我們啟動了 Python 分析器,開始調查速度慢的原因。還記得上文提到我們有22個支援向量機,每個單詞都會通過它們處理嗎?原來這個過程是按順序進行,而不是並行的。好了,第一個想法是換成類似分散式計算系統(map/reduce)的處理器。長話短說:Python 不適合用 map/reduce。當你需要併發性的時候,Python 並不能幫上忙。在 Pycon 2013大會中,Guido 談到了 Tulip,他希望用來解決這個問題的一個新專案,但是還要過一段時間才能釋出。可是,如果已經有了更好的選擇,為什麼還要苦等下去呢?
選擇 Golang 還是回老家(Go Home)
在 Mozilla 的朋友告訴筆者,Mozilla 服務的日誌架構大部分程式碼都已遷移到 Go,部分原因是 goroutines 超級便利。Go 是由谷歌員工開發的,設計之初就將併發需求列為一級理念,而不是像 Python 的眾多解決方案一樣在做事後補救。因此我們開始著手實現從 Python 到 Go 的遷移。
雖然 Go 程式碼還沒實現大規模產出,得到的結果已經非常振奮人心。我們現在一秒鐘能處理1000個文件,使用的記憶體大大減少,而且也不用再去除錯和解決使用 Python 時會遇到的多程式/協程(gevent)/“為什麼 Control-C 殺死了我的程式”等問題。
喜歡 Go 的原因
任何略懂程式語言的人(明白解釋與編譯、動態與靜態區別)都會說:“哈,顯然 Go 要快多了。”沒錯,我們是可以用 Java 重寫所有內容,並且取得類似的效果,但是這並不是 Go 勝出的原因。你用 Go 寫的程式碼似乎一出來是正確的。筆者也說不清楚,但是不知怎麼的,一旦程式碼被編譯(編譯過程非常迅速),你就會感覺它能工作了(不只是執行不出錯,而且還邏輯正確)。這聽起來很含糊,但是它是真的。在冗餘或無冗餘方面,它跟 Python 相似,它把函式當做一級物件,因此函式程式設計很方便。而且毋庸置疑,goroutines 和 channels 會讓你更加省心省力。靜態型別還會帶來極大的效能提升,以及更精確的記憶體分配控制,但是又不會損失太多表達性。
早該知道的事
除去溢美之詞,跟 Go 打交道需要與 Python 完全不同的一套思維模式。以下列出的是筆者在遷移時做的一些筆記——都是在從 Python 遷移到 Go 時隨機想到的一些東西:
- 沒有內建的集合型別(需要使用 map,然後測試存在性)
- 由於沒有集合型別,需要自己寫程式碼來實現交集、並集等方法
- 無元組(tuple),必須自己寫架構或使用切片(slice)(陣列)
- 沒有類似 getattr_() 的方法,因此需要不斷檢查存在性,而不能像在 Python 中那樣設定預設值:value = dict.get(“a_key”, “default_value”)
- 必須不斷檢查錯誤(至少需要顯式忽略它們)
- 不能包含未使用的變數或包,因此有時候如果要測試一些簡單問題,需要給程式碼新增註釋
- 在 []byte 和 string 之間切換。正則表達 (regexp) 使用 []byte (可變)。這說得通,但是在一些變數之間來回切換還是很煩人
- Python 更為寬鬆。你可以用超出範圍的索引來索取字串片段,也不會有什麼問題,還可以提取負值片段,但是 Go 就不行
- ~~不能使用混合型別的資料結構。也許不合規定,但是有時候在 Python 可以使用混合字串和列表的字典。在 Go 就不行,要麼清理乾淨資料結構,要麼自定義結構。~~感謝 Ralph Corderoy 向筆者展示瞭如何正確操作(用這個介面,盧克) http://play.golang.org/p/SUgl7wd9tk
- 不能把元組或列表分解成分開的變數(如 x,y,x = [1,2,3])
- 駝峰字規則(UpperCamelCase)(如果一個包中的函式或結構首字母未大寫,就不會暴露給其他包)。筆者更喜歡 Python 的小寫加下劃線格式(lower_case_with_underscores)
- 需要顯式檢查錯誤是否為 != nil,不像 Python 有很多型別可以用於布林型檢查(0,“”,None 都會被解讀為“假”)
- 某些模組(如 crypto/md5)的文件不足,但是 IRC 上面的 go-nuts 非常棒,擁有特別好的支援
- 從數字到字串的型別轉換(int64 -> 字串)跟[]byte -> 字串(只用字串([]byte))不同,需要用到 strconv
- Go 的程式碼讀起來更像是程式語言,而 Python寫出來更像虛擬碼。Go 包含更多非數字字母字元,用 || 和 && 來表示“或”與“和”
- 寫檔案會有 File.Write([]byte) 和File.WriteString(string),這會讓習慣了 Python 只有一種做事方法的開發者們有些不適應
- 字串插入很麻煩,不得不經常使用 fmt.Sprintf
- 沒有建構函式,常見的做法是建立 NewType() 函式,來返回你需要的結構
- Else 或 else if 必須格式正確,else 得跟 if 從句的大括號在一行。這很奇怪。
- 根據函式內外位置,使用不同的賦值操作符,例如 = 和 :=
- 如果只想要類似dict.keys() 或dict.values()得到的鍵值或取值列表,或者通過
- dict.items()得到的元祖列表,在 Go 裡面是無法實現的,只能自行迭代 map,然後建立自己的列表
- 筆者習慣建立一個取值為函式的字典,並通過鍵值呼叫函式。你可以在 Go 裡面這麼做,但是所有的函式都得接受和返回同樣的東西,也就是說,必須具備同樣的方法簽名
- 如果你是用 JSON, 而且是混合型別的 JSON,那麼你還是自求多福吧。你得建立一個能夠匹配你的 JSON 二進位制大物件(blob)格式的個性化結構,然後解組(Unmarshall)原始 JSON 成為你的個性化架構的一個用例。比起在 Python 中的一句“obj = json.loads(json_blob)”要費更多功夫
這麼折騰值得嗎?
值,一百萬個值,超值。速度的提升不容忽視。而且筆者認為這也是促使 Go 成為流行語言的重要原因。因此在招聘時,筆者認為把 Go 當成 Python 開發者的必備技能也很重要。
OneAPM 能幫你檢視 Python 應用程式的方方面面,不僅能夠監控終端的使用者體驗://blog.oneapm.com/tags-%E7%94%A8%E6%88%B7%E4%BD%93%E9%AA%8C.html,還能監控伺服器效能,同時還支援追蹤資料庫、第三方 API 和 Web 伺服器的各種問題。想閱讀更多技術文章,請訪問 OneAPM 官方技術部落格。
本文轉自 OneAPM 官方部落格
原文地址: https://blog.repustate.com/migrating-code-from-python-to-golang-what-you-need-to-know/
相關文章
- Python 開發者在遷移到 Go 前需要知道的事情PythonGo
- Mysql遷移到Oracle前需要了解的50件事MySqlOracle
- 獨立遊戲開發者需要知道的事實遊戲開發
- 從Oracle遷移到Mysql之前必須知道的50件事OracleMySql
- Python開發者在轉到Go語言之前需要了解什麼?PythonGo
- 如果需要從Oracle遷移到MS SQLServer (2)OracleSQLServer
- 如果需要從Oracle遷移到MS SQLServer (1)OracleSQLServer
- 在將單體遷移到微服務之前需要了解的模式 - Abhishek微服務模式
- Python 決定遷移到 GitHubPythonGithub
- SQL Azure萬事俱備,使用者需要在12月前遷移到新的CTP上SQL
- 你的資料庫真的需要遷移到雲嗎?資料庫
- 企業遷移到公有云之前的注意事項
- sqlzoo需要知道的那些事SQL
- Python 將所有 Bug 遷移到 GitHub 中PythonGithub
- 遷移到ASMASM
- ?Web開發者需要知道的CSS TricksWebCSS
- Flex開發者需要知道的10件事Flex
- Flash開發者需要知道的10件事
- svn 遷移到gitGit
- svn遷移到gitGit
- SQLITE 遷移到 MYSQLSQLiteMySql
- 學習機器學習時需要儘早知道的三件事機器學習
- 【遷移】SqlServer 遷移到 MySQL 方法ServerMySql
- Python命名規則是什麼?需要注意哪些事項?Python
- 從過時的 Windows 機器遷移到 LinuxWindowsLinux
- 在釋出站點前,Web開發者需要關注哪些技術細節?Web
- 在釋出站點前 Web開發者需要關注哪些技術細節?Web
- Flutter 你需要知道的那些事 01Flutter
- 為什麼你會遷移到Python3.5 ?Python
- 在使用Redux前你需要知道關於React的8件事ReduxReact
- 口袋妖怪Pokémon GO遷移到谷歌Kubernetes容器雲Go谷歌
- 什麼是工時管理系統?企業使用時需要注意哪些事項
- 從Perforce遷移到GitGit
- blog遷移到此
- WSL遷移到其他磁碟
- Raspberry Pi with Go langGo
- Oracle遷移到PPAS(PostgreSQL)時的日期計算問題OracleSQL
- 關於CSS Transition,你需要知道的事CSS