Python 開(kāi)發(fā)者在遷移到 Go(lang) 時(shí)需要知道哪些事?

【編者按】本文最早由 Repustate 發(fā)布,主要介紹將代碼遷移至 Go(lang) 時(shí)的注意事項(xiàng)。文章系國(guó)內(nèi) ITOM 管理平臺(tái) OneAPM 編譯呈現(xiàn),以下為正文。

這是一篇講述將大塊 Python/Cython 代碼遷移到 Go 的長(zhǎng)文章。如果你想了解整個(gè)事情的經(jīng)過(guò)、背景等所有信息,請(qǐng)讀下去。如果你只對(duì) Python 開(kāi)發(fā)者需要了解的事感興趣,請(qǐng)下拉到早該知道的事板塊。

背景

我們?cè)?Repustate 最大的技術(shù)成果就是實(shí)現(xiàn)了阿拉伯語(yǔ)情感分析。阿拉伯語(yǔ)是個(gè)難啃的硬骨頭,因?yàn)榘⒗Z(yǔ)詞匯的形式非常復(fù)雜。阿拉伯語(yǔ)的標(biāo)記化(把一句話(huà)拆分成單個(gè)單詞)也比英語(yǔ)要難得多,因?yàn)榘⒗畣卧~內(nèi)部可能會(huì)包含空格(例如單詞內(nèi)部“aleph”的位置)。在不泄露機(jī)密的情況下,Repustate 利用支持向量機(jī)(SVM)來(lái)獲取一個(gè)句子最可能的意思,并且以此來(lái)推斷句子的情感。我們一共采用了22種模型(22個(gè)支持向量機(jī)),文檔中的每個(gè)詞都會(huì)被分析。也就是說(shuō),如果一個(gè)文檔包含500個(gè)詞,就會(huì)與支持向量機(jī)進(jìn)行10000多次對(duì)比。

Python

Repustate 幾乎完全是用 Python 搭建的,我們使用 Django 來(lái)搭建 API 接口和網(wǎng)站架構(gòu)。因此,為了保持代碼一致性,使用 Python 來(lái)實(shí)現(xiàn)所有阿拉伯語(yǔ)情感引擎才說(shuō)得通。就原型設(shè)計(jì)和實(shí)現(xiàn)流程而言,Python 依然是一個(gè)很好的選擇:表現(xiàn)能力優(yōu)秀,又有強(qiáng)大的第三方庫(kù)資源,等等。如果是服務(wù)于網(wǎng)頁(yè),它就是最佳選擇。如果是稍低級(jí)別的運(yùn)算,需要與哈希表(Python 中的字典)進(jìn)行大量對(duì)比時(shí),運(yùn)行速度就會(huì)慢下來(lái)。我們一秒鐘只能處理2到3個(gè)阿拉伯語(yǔ)單詞,這種速度太慢了。相比之下,我們的英語(yǔ)情感引擎每秒能處理500個(gè)單詞。

瓶頸

因此,我們啟動(dòng)了 Python 分析器,開(kāi)始調(diào)查速度慢的原因。還記得上文提到我們有22個(gè)支持向量機(jī),每個(gè)單詞都會(huì)通過(guò)它們處理嗎?原來(lái)這個(gè)過(guò)程是按順序進(jìn)行,而不是并行的。好了,第一個(gè)想法是換成類(lèi)似分布式計(jì)算系統(tǒng)(map/reduce)的處理器。長(zhǎng)話(huà)短說(shuō):Python 不適合用 map/reduce。當(dāng)你需要并發(fā)性的時(shí)候,Python 并不能幫上忙。在 Pycon 2013大會(huì)中,Guido 談到了 Tulip,他希望用來(lái)解決這個(gè)問(wèn)題的一個(gè)新項(xiàng)目,但是還要過(guò)一段時(shí)間才能發(fā)布??墒?,如果已經(jīng)有了更好的選擇,為什么還要苦等下去呢?

選擇 Golang 還是回老家(Go Home)

在 Mozilla 的朋友告訴筆者,Mozilla 服務(wù)的日志架構(gòu)大部分代碼都已遷移到 Go,部分原因是 goroutines 超級(jí)便利。Go 是由谷歌員工開(kāi)發(fā)的,設(shè)計(jì)之初就將并發(fā)需求列為一級(jí)理念,而不是像 Python 的眾多解決方案一樣在做事后補(bǔ)救。因此我們開(kāi)始著手實(shí)現(xiàn)從 Python 到 Go 的遷移。

雖然 Go 代碼還沒(méi)實(shí)現(xiàn)大規(guī)模產(chǎn)出,得到的結(jié)果已經(jīng)非常振奮人心。我們現(xiàn)在一秒鐘能處理1000個(gè)文檔,使用的內(nèi)存大大減少,而且也不用再去調(diào)試和解決使用 Python 時(shí)會(huì)遇到的多進(jìn)程/協(xié)程(gevent)/“為什么 Control-C 殺死了我的進(jìn)程”等問(wèn)題。

喜歡 Go 的原因

任何略懂編程語(yǔ)言的人(明白解釋與編譯、動(dòng)態(tài)與靜態(tài)區(qū)別)都會(huì)說(shuō):“哈,顯然 Go 要快多了?!睕](méi)錯(cuò),我們是可以用 Java 重寫(xiě)所有內(nèi)容,并且取得類(lèi)似的效果,但是這并不是 Go 勝出的原因。你用 Go 寫(xiě)的代碼似乎一出來(lái)是正確的。筆者也說(shuō)不清楚,但是不知怎么的,一旦代碼被編譯(編譯過(guò)程非常迅速),你就會(huì)感覺(jué)它能工作了(不只是運(yùn)行不出錯(cuò),而且還邏輯正確)。這聽(tīng)起來(lái)很含糊,但是它是真的。在冗余或無(wú)冗余方面,它跟 Python 相似,它把函數(shù)當(dāng)做一級(jí)對(duì)象,因此函數(shù)編程很方便。而且毋庸置疑,goroutines 和 channels 會(huì)讓你更加省心省力。靜態(tài)類(lèi)型還會(huì)帶來(lái)極大的性能提升,以及更精確的內(nèi)存分配控制,但是又不會(huì)損失太多表達(dá)性。

早該知道的事

除去溢美之詞,跟 Go 打交道需要與 Python 完全不同的一套思維模式。以下列出的是筆者在遷移時(shí)做的一些筆記——都是在從 Python 遷移到 Go 時(shí)隨機(jī)想到的一些東西:

  • 沒(méi)有內(nèi)建的集合類(lèi)型(需要使用 map,然后測(cè)試存在性)
  • 由于沒(méi)有集合類(lèi)型,需要自己寫(xiě)代碼來(lái)實(shí)現(xiàn)交集、并集等方法
  • 無(wú)元組(tuple),必須自己寫(xiě)架構(gòu)或使用切片(slice)(數(shù)組)
  • 沒(méi)有類(lèi)似 getattr_() 的方法,因此需要不斷檢查存在性,而不能像在 Python 中那樣設(shè)置缺省值:value = dict.get(“a_key”, “default_value”)
  • 必須不斷檢查錯(cuò)誤(至少需要顯式忽略它們)
  • 不能包含未使用的變量或包,因此有時(shí)候如果要測(cè)試一些簡(jiǎn)單問(wèn)題,需要給代碼添加注釋
  • 在 []byte 和 string 之間切換。正則表達(dá) (regexp) 使用 []byte (可變)。這說(shuō)得通,但是在一些變量之間來(lái)回切換還是很煩人
  • Python 更為寬松。你可以用超出范圍的索引來(lái)索取字符串片段,也不會(huì)有什么問(wèn)題,還可以提取負(fù)值片段,但是 Go 就不行
  • 不能使用混合類(lèi)型的數(shù)據(jù)結(jié)構(gòu)。也許不合規(guī)定,但是有時(shí)候在 Python 可以使用混合字符串和列表的字典。在 Go 就不行,要么清理干凈數(shù)據(jù)結(jié)構(gòu),要么自定義結(jié)構(gòu)。感謝 Ralph Corderoy 向筆者展示了如何正確操作(用這個(gè)界面,盧克)
    http://play.golang.org/p/SUgl7wd9tk
  • 不能把元組或列表分解成分開(kāi)的變量(如 x,y,x = [1,2,3])
  • 駝峰字規(guī)則(UpperCamelCase)(如果一個(gè)包中的函數(shù)或結(jié)構(gòu)首字母未大寫(xiě),就不會(huì)暴露給其他包)。筆者更喜歡 Python 的小寫(xiě)加下劃線(xiàn)格式(lower_case_with_underscores)
  • 需要顯式檢查錯(cuò)誤是否為 != nil,不像 Python 有很多類(lèi)型可以用于布爾型檢查(0,“”,None 都會(huì)被解讀為“假”)
  • 某些模塊(如 crypto/md5)的文檔不足,但是 IRC 上面的 go-nuts 非常棒,擁有特別好的支持
  • 從數(shù)字到字符串的類(lèi)型轉(zhuǎn)換(int64 -> 字符串)跟[]byte -> 字符串(只用字符串([]byte))不同,需要用到 strconv
  • Go 的代碼讀起來(lái)更像是編程語(yǔ)言,而 Python寫(xiě)出來(lái)更像偽代碼。Go 包含更多非數(shù)字字母字符,用 || 和 && 來(lái)表示“或”與“和”
  • 寫(xiě)文件會(huì)有 File.Write([]byte) 和File.WriteString(string),這會(huì)讓習(xí)慣了 Python
    只有一種做事方法的開(kāi)發(fā)者們有些不適應(yīng)
  • 字符串插入很麻煩,不得不經(jīng)常使用 fmt.Sprintf
  • 沒(méi)有構(gòu)造函數(shù),常見(jiàn)的做法是創(chuàng)建 NewType() 函數(shù),來(lái)返回你需要的結(jié)構(gòu)
  • Else 或 else if 必須格式正確,else 得跟 if 從句的大括號(hào)在一行。這很奇怪。
  • 根據(jù)函數(shù)內(nèi)外位置,使用不同的賦值操作符,例如 = 和 :=
  • 如果只想要類(lèi)似dict.keys() 或dict.values()得到的鍵值或取值列表,或者通過(guò)
  • dict.items()得到的元祖列表,在 Go 里面是無(wú)法實(shí)現(xiàn)的,只能自行迭代 map,然后創(chuàng)建自己的列表
  • 筆者習(xí)慣建立一個(gè)取值為函數(shù)的字典,并通過(guò)鍵值調(diào)用函數(shù)。你可以在 Go
    里面這么做,但是所有的函數(shù)都得接受和返回同樣的東西,也就是說(shuō),必須具備同樣的方法簽名
  • 如果你是用 JSON, 而且是混合類(lèi)型的 JSON,那么你還是自求多福吧。你得創(chuàng)建一個(gè)能夠匹配你的 JSON 二進(jìn)制大對(duì)象(blob)格式的個(gè)性化結(jié)構(gòu),然后解組(Unmarshall)原始 JSON 成為你的個(gè)性化架構(gòu)的一個(gè)用例。比起在 Python 中的一句“obj = json.loads(json_blob)”要費(fèi)更多功夫

這么折騰值得嗎?

值,一百萬(wàn)個(gè)值,超值。速度的提升不容忽視。而且筆者認(rèn)為這也是促使 Go 成為流行語(yǔ)言的重要原因。因此在招聘時(shí),筆者認(rèn)為把 Go 當(dāng)成 Python 開(kāi)發(fā)者的必備技能也很重要。

OneAPM 能幫你查看 Python 應(yīng)用程序的方方面面,不僅能夠監(jiān)控終端的用戶(hù)體驗(yàn)://blog.oneapm.com/tags-%E7%94%A8%E6%88%B7%E4%BD%93%E9%AA%8C.html,還能監(jiān)控服務(wù)器性能,同時(shí)還支持追蹤數(shù)據(jù)庫(kù)、第三方 API 和 Web 服務(wù)器的各種問(wèn)題。想閱讀更多技術(shù)文章,請(qǐng)?jiān)L問(wèn) OneAPM 官方技術(shù)博客

本文轉(zhuǎn)自 OneAPM 官方博客

原文地址: https://blog.repustate.com/migrating-code-from-python-to-golang-what-you-need-to-know/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,732評(píng)論 6 539
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,214評(píng)論 3 426
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事?!?“怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 177,781評(píng)論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,588評(píng)論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,315評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,699評(píng)論 1 327
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,698評(píng)論 3 446
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,882評(píng)論 0 289
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,441評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,189評(píng)論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,388評(píng)論 1 372
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,933評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,613評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 35,023評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 36,310評(píng)論 1 293
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,112評(píng)論 3 398
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,334評(píng)論 2 377

推薦閱讀更多精彩內(nèi)容

  • # Python 資源大全中文版 我想很多程序員應(yīng)該記得 GitHub 上有一個(gè) Awesome - XXX 系列...
    aimaile閱讀 26,533評(píng)論 6 427
  • http://python.jobbole.com/85231/ 關(guān)于專(zhuān)業(yè)技能寫(xiě)完項(xiàng)目接著寫(xiě)寫(xiě)一名3年工作經(jīng)驗(yàn)的J...
    燕京博士閱讀 7,605評(píng)論 1 118
  • 環(huán)境管理管理Python版本和環(huán)境的工具。p–非常簡(jiǎn)單的交互式python版本管理工具。pyenv–簡(jiǎn)單的Pyth...
    MrHamster閱讀 3,812評(píng)論 1 61
  • GitHub 上有一個(gè) Awesome - XXX 系列的資源整理,資源非常豐富,涉及面非常廣。awesome-p...
    若與閱讀 18,693評(píng)論 4 418
  • 《涼涼就是好〉 曾經(jīng)有一天,一場(chǎng)大雨初晴,大寨街道上這兒積一灘水,那兒匯〃一條小河“,到處惹眼滑溜閃亮。就在這天,...
    山上丑石_ef19閱讀 174評(píng)論 0 0