專訪Elton:淺談C++、Go的挑戰者Rust
鐘宇騰(Elton, GitHub 、 LinkedIn ),香港大學計算機系畢業,微信游戲開發組工程師。
CSDN:首先介紹下你自己及目前所從事的工作。
Elton: 我是香港大學計算機系研究生畢業,本科在中山大學計算機系。目前正在微信游戲工作,崗位是后臺開發。
我接觸計算機也算是比較早的,記得當時家里的電腦跑的是DOS,我經常看著老爸在電腦里敲著各種命令,然后屏幕的字就刷刷刷出來,感覺非常好奇, 現在想起來依然記得當初在電腦上敲下的第一個命令:dir,然后看著屏幕刷出來的白字。雖然一點都看不懂那是什么意思,但覺得非常好玩。
快升初中的時候,老爸給我買了一個在電腦上跑的學習軟件,并要求我每天都要在上面去做題,于是當時就學會了怎么讀軟盤,然后在DOS上進入軟盤然后執行那個軟件,再換其它軟盤來把題目讀出來,再做。
初中的時候,家里的電腦由于被我自己弄壞了很多次,已經可以熟練安裝Windows 98/2000/ME,在學校里面,也是經常到辦公室幫老師 重裝系統。后來家里電腦再次升了個級,終于可以安裝XP了,當時是自己到電腦城買的盜版光盤(當時并不知道這是盜版的),然后在家里裝上,還能想起當時安 裝完XP進入界面后,一邊感嘆絢麗的界面,一邊把各種功能都點了個遍。
最初接觸編程也是在初中,當時學校要舉辦班級網頁大賽,因為在老師那里名聲在外,自然而然地代表班級參賽。下載了FrontPage和 DreamWeaver,然后去書店買了兩本書依葫蘆畫瓢,拖控件做出了個靜態的網站。有時覺得直接拖不好看,于是就點進源代碼去試,雖然不懂,但還是靠 猜和無數的嘗試,做出了自己滿意的效果,在大賽中也獲得不錯的成績(好像是第一名,但已經不記得了)。之后高中(同一個學校),又被拉去做班級網頁大賽, 這次就不光是做了個靜態的,還在網上搜索到了不少的可以實現某些特殊效果的JavaScript或者是VBScript的腳本,雖然也是完全不懂,靠摸索 修改各種參數,把它嵌入到自己的網站然后調試出自己想要的效果。記得當時為了這個網站,每天晚上自習回家,一直弄到12點之后,各種調試,樂在其中哈。
說說第一次接觸Linux,那是高三的時候,一天一個同學跟我說,我在網上看到一個好漂亮的系統叫做Ubuntu,你要不要看一下?然后搜索發現 了各種Ubuntu的漂亮的效果圖,大多是Compiz弄出來的效果,然后很果斷地,下載了Ubuntu 9.04的ISO,刻盤,安裝,一氣呵成。但是 問題一下子就來了,想安裝軟件,完全不會!搜索只看到Ubuntu Forum,進去發現很多人都在講,在終端里輸 入 ./configure, make, sudo make install就可以啦,然后我花了一個星期,才搞明白,終端原來是那個在菜單里找到的 叫終端的一個軟件(Gnome 2),然后再花了一個星期通過搜索搞明白了什么叫目錄結構,學會了少數幾個shell命令,終于從終端進入到了那個文件 夾,然后輸入了那三板斧。之后的一個月,就是一直利用搜索引擎解決各種遇到的問題,終于把那個軟件裝了上去,成功入門。
之后到了大學,如愿上了計算機系,系統地學習了各種計算機領域的知識。
CSDN:你的 Rust 之路是怎樣的?
Elton: 認識Rust是在大三的時候,我在網上(不記得是哪里了)有介紹Rust這一門新的編程語言,然后好奇就點進去官網看,當時版本好像是0.9dev吧,語 法和現在可差遠了。進Documentation讀了兩章發現這語言的設計有意思啊,指針雖然分了非常多種,還有個神奇的Lifetime的概念,認真讀 下來感覺和寫C++程序的時候差不多,只不過這門語言想要在編譯期就檢測出大多數的錯誤,很有趣。于是向一個小伙伴介紹了這門語言,讓他和我一起學習。學 完基礎之后,我就想做一個小項目來更好的理解這門語言,就選了做一個INI庫(rust-ini)。這是我的第一個Rust項目,之后每一次Rust語法 更新,因為強迫癥的原因,就被迫讀更新日志,然后根據更新修改項目讓它可以在新的編譯器下編譯。
之后第二個項目就是shadowsocks-rust,因為GoAgent越來越不好用了,用了一些日子的V*N,就萌生了想自己寫一個V*N, 然后搭在linode上。當時混V2EX發現很多人都在聊ShadowSocks,花了一天把源代碼讀了一遍,感覺非常好實現,花了一個星期做出了初版, 之后也是跟著Rust的版本一起升級,經歷過幾次大的變動,代碼混亂不堪,最近有點時間,順便利用了一下coroutine-rs這個協程庫,把它重構成 協程版。
CSDN:你在 GitHub 上組織和帶領了多個項目,能不能詳細說下經過?其中有沒有什么有趣的事情?
Elton: 在Github上大多都是自己的個人項目,說到帶領的話,coroutine-rs應該算是一個。當時在Rust中文社區的群里面,發現Young在研究 libgreen(Rust早期0.12dev版本官方實現的一個協程庫,后來已廢棄),自己也在做相關的東西,兩人一拍即合,合作做出了 coroutine-rs。
rust-ini 是我學習Rust時做的第一個項目,經歷過好多次的改版,最近的一次改版是為了試一下Rust標準庫的Cow(Copy-on-write)庫,把整個項目改了。
jsonrpc-rs 是最近和最初一起學習的那位小伙伴一起合作的項目,項目的主要原因是為了探索一種好的RPC庫的設計。
bson-rs 項目實現了一個BSON庫,這個純粹就是因為無聊,然后看到了BSON的Specification,花了一天寫出來的。現在有幾個團隊想用我這個庫去實現MongoDB的Rust driver。
simplesched 和 eventedco 是基于coroutine-rs實現的調度器(Scheduler),包含各種Non- blocking I/O的支持。實際上我是想做成像Go那樣的Work-stealing Scheduler,但是因為做了一個月發現做出來效率很 差,就先退而求其次,放出了兩個不同思路的簡單的版本。
memcached-rs 這個也是一個周末,看了Memcached的幾個Client實現之后,心血來潮,花了幾天時間實現了一個Client庫,最近在計劃用Rust克隆一個Memcached,為了學習Memcached的設計。
其它的項目跟Rust關系不大,都是一些個人的興趣項目,其中小部分是在學校的課程項目。
CSDN:你是何時、如何成為微信團隊的一員?其中面試過程,你有什么心得體會可分享?
Elton: 去年10月的時候面試微信團隊的。騰訊的面試相信大家在網上都能了解一二。面試內容無非一些基礎的函數實現,還有操作系統相關的一些知識的題目,問到的知識我在學習的過程中都有深入了解過,因此面試非常順利地就通過了。
CSDN:能否談一下,你畢業時為何選擇到騰訊工作?畢竟家里人想要遷居香港且希望你在香港工作。
Elton: 我曾經想過在香港工作,也面試了一家創業公司,組長非常看好我,老板也給也給出了很不錯的薪資。但考慮過后我還是放棄了,回到深圳騰訊。主要是感覺香港的IT業沒有深圳繁榮,雖然有不少的創業公司,但我個人還是希望先到大公司積累經驗,以后再考慮創業公司闖蕩。
Rust需要一個大公司帶頭做出一個成功的產品作為案例
CSDN:Rust 是一種怎樣的語言?相比競爭對手 C/C++ 幾何?各自的特點是什么?
Elton: Rust是一門系統編程語言,系統編程語言說明它有直接操作硬件的能力,就像C/C++一樣,但是它還有一個重要的特性,那就是安全。在C/C++里面, 很容易會因為內存管理的問題而出現Segmentation Fault,在Rust中,由于引入了所有權(Ownership)和生存期 (Lifetime)的概念,實現了自動內存管理的同時,還避免了各種內存錯誤。但同時,也提供unsafe塊和祼指針(Raw Pointer),提供 更多的自由度。
在Rust中,還支持高階函數(閉包,Closure),C++11 之后也提供了Lambda來支持閉包,但在C中還沒有。
模式匹配(Pattern Match)和ADT(Algebraic Data Type),在C/C++中都沒有提供。模式匹配和ADT在許 多函數式編程語言中都作為標準來提供了。有了ADT,可以把許多操作都統一起來,并且利用模式匹配可以很方便地把其中的數據取出來。
默認情況下不可變,這在C/C++中是完全相反。默認不可變更有利于編譯器優化,而且不可變對于寫并發程序有不少的好處。
CSDN:Rust 學習中新人要注意哪些問題?
Elton: 新人剛接觸Rust,特別是沒有接觸過函數式編程語言的新人,首先可能會被模式匹配、跟C/C++/Java等完全不同的枚舉類型,還有各種指針類型難住。
其次,繼續學習下去會發現Trait based OO跟以前接觸的OO完全不同。
再之,深入學習的時候,對象所有權還有生存期的概念看起來完全不知道在講什么。
最后,上手實踐的時候:天哪,編譯器我到底寫錯什么了啊!你好好說話啊!!
我就是一步步這樣過來的,當時也沒有接觸過函數式編程語言,后來才學習了Haskell才深入理解了Rust中的ADT和模式匹配。對于平時習慣 高級語言的新人,我建議在學習的時候,不要試圖把Rust的一些概念直接套入到自己習慣的語言中去,因為那是肯定不可能的,而且還會影響你理解。對于語法 上的不理解,建議使用play.rust-lang.org來學習,看完之后實際操作一下,在例子上做一些小修改嘗試讓它跑起來,不明白的地方找個人一起 交流(現實中找一個小伙伴一起學習是最好的辦法)。
在理解對象所有權及生存期的時候,文檔讀起來非常晦澀,可能會讓人產生非常大的挫敗感。其實,建議先從例子開始一步步理解:
所有權講的是Ownership,思考一下當前對象的Owner是誰?如果用了Borrowed Pointer,那它被借給了誰?是可變的還是不可變的?
如果代碼中有顯式的Lifetime,如下例子
fn test<'a>(s: &'a str) -> &'a str {
s
}
當我這樣調用函數時
let hello = "hello"; let hello2 = test(hello);
'a 是多少?因為 "hello" 的類型是 &'static str,所以生存期是 'static,把它代入到函數聲明,就會發現,'a 就是 'static。絕大多數情況生存期都可以這樣一步步的推導出來,并不難。
Rust編譯器還嫩,許多錯誤提示還做不到很智能,因此錯誤會非常晦澀。遇到一直編譯不過的問題,可以先弄一個 Minimal Test Case,確定錯誤可以重現之后,把它拿出來一起討論,Rust中文社區的群是一個非常好的交流地點,另一個就是Rust官方 IRC,那上面幾乎是有求必應。
CSDN:Rust 中有哪些坑?
Elton: 簡單來說,有以下這些:
- Rust不支持默認參數,也不支持可變長的參數;
- Lifetime不要亂寫,有時可能一時編譯可以過,但在另外的地方使用的時候會出現各自神奇的錯誤,錯誤提示會一直都在調用的地方,因為編譯器相信你寫的Lifetime是對的,它從不懷疑;
- Rust沒有屬性繼承,所以只能用組合的方式;
- 標準庫和第三方庫還需要完善。
CSDN:你是否有一個比較系統的Rust資料來分享給你有興趣的開發者?
Elton: 實際上,我自己用得最多的Rust資料就是官方文檔。每一周看一下http://this-week-in-rust.org,看看官方最近有什么進展,有什么讓人驚喜的改進,或者是好的新項目可以使用或參與。
CSDN:Rust 如何才能吸引開發者?最能吸引哪個群體?
Elton: Rust最吸引的開發者群體相信就是C/C++開發者,同樣是關注性能的系統編程,C/C++群體想要轉到Rust的難度應該是最小的。而且Rust解決了C++的不少弊端。
Mike :Rust對動態語言界的吸引力如何? (Mike,唐剛,媽咪問問CEO和Rust使用者)
Elton: 動態語言普遍都帶GC,而且比較少關注系統編程以及內存管理,對于Rust的強制編譯期檢查所有權和生存期,在學習時有可能會遇到不小的挫敗感。但動態語 言在項目變大之后,會變得越來越難以維護,于是近年又開始從動態類型的語言向靜態類型語言遷移,比較有代表性的就是Go、HHVM,Python 3.5 的Type Hints。
Mike : 那Rust和Go各自優缺點是怎樣的?Rust是不是會蓋過Go?
Elton: 網上對于Rust和Go到底是不是競爭者有不小的爭論,我認為Rust和Go在大多數領域并不是競爭者。Go是為了方便開發高并發的服務器,而Rust的 目標是系統編程,關注內存安全、并發安全等。從目前來看,很難說Rust會蓋過Go,Rust沒有Go那么易上手,復雜的類型系統、所有權還有生存期的概 念會難住不少編程新手,但真正用熟悉之后會發現Rust用起來比Go舒服太多。Rust更多會吸引一些C/C++擅長的領域,比如游戲開發、嵌入式開發 等。
Mike : Rust在游戲領域有沒作為?此外,Rust在教育培訓方面有沒機會?
Elton: 游戲開發主要關注性能,一直都是C++的固有領土。Rust目前剛推出,性能已經接近C/C++,已經有團隊在著手實現 用Rust寫的游戲引擎Piston ,項目雖然還在早期,但已有不少成果。
在University of Virginia,有位教授開了一門本科的操作系統課, 使用Rust作為教學語言 ,從這個網頁可以看到學生的反饋,大多數學生還是比較喜歡使用Rust作為教學語言的。
Young:講講trait system如何解決現有開發中的痛處? (Young,吳畏遠,UESTC學生, Strikingly 數據工程師,Rust使用者。)
Elton: Trait實際上就是定義了一些方法,與Java的Interface的不同點就是,Trait可以給方法提供默認實現。這看起來并沒有什么特別的,但是 Trait帶來了一個顯而易見的好處:避免了多繼承和方法命名沖突,不同的Trait可以有完全相同的方法簽名,它們可以同時被同一個struct實現, 例如
trait Foo { fn who(&self); } trait Bar { fn who(&self); } struct Dummy; impl Foo for Dummy { fn who(&self) { println!(“Dummy Foo”); } } impl Bar for Dummy { fn who(&self) { println!(“Dummy Bar”); } }
從上面例子可以看到,Dummy實現了Foo和Bar,而Foo和Bar有一個命名簽名完全一樣的方法fn who(&self),那么調用的時候可以這樣
let dummy = Dummy; Foo::who(&dummy); // 調用Foo::who Bar::who(&dummy); // 調用Bar::who
這種在Rust中叫作UFCS(UniversalFunctional Call Syntax)。
配合泛型使用,Trait可以實現很多非常方便的功能。比如在Rust里面,就用Send這個類型來約束一個struct是否可以安全地傳遞到另一個線程,而Sync可以表示一個struct是否可以安全地在不同的線程之間共享。
另外,借助impl,可以為已有的類型實現自定義的Trait,比如
trait Foo { fn hello(&self); } impl Foo for i32 { fn hello(&self) { println!(“Hello from {}”, self); } }
于是就可以這樣 1.hello() 調用,然后輸出 “Hello from 1”。
隨著互聯網發展,開發主要目標漸漸轉移到移動和web,那么Rust能否很方便的進軍Android/iOS開發呢?在WebAssembly的地盤是否能從c++那分一杯羹呢?
起碼在Android上,使用JNI直接調用Rust交叉編譯得到的動態鏈接庫,那是肯定沒有問題的,目前也已經有人在做: https://github.com/tomaka/android-rs-glue 。
對于iOS,有人還給出了教程: https://www.bignerdranch.com/blog/building-an-ios-app-in-rust-part-1/ 。
但這些例子只說明了是可行的,但實用性如何,得真正應用到生產環境中才能知道。我個人不做客戶端方面的東西,所以我就不知道了。
CSDN:我們知道國內的Rust應用情況極差,你能談談原因是是什么嗎?國外有哪些比較好的應用案例?
Elton: 實際上,國外也不見得有什么好的案例,日前剛在IRC上看到有Dropbox的員工在問Rust相關的事情,可能是要在項目中使用。Rust的1.0在今年才出,很少會有公司愿意冒險去做第一個吃螃蟹的人。Go 1.0是2012年推出的,火也是近一兩年的事情。
簡而言之,Rust需要一個大公司帶頭做出一個成功的產品作為案例。
CSDN:Rust能站住腳么? 對 Rust 未來發展你如何看?
Elton: 對Rust語言的未來非常看好,除了因為它是業界大佬Mozilla出品,還因為它準確擊中了C/C++程序員的痛點,可以完美實現底層操作的同時,在編 譯時實現內存管理和錯誤檢查,程序運行性能還不錯,非常接近C/C++。但Rust的生態系統還需要完善,若能有其它大公司的參與,相關的可以提高生產力 的庫才能夠完善。
CSDN : 對于推廣Rust語言有什么好的建議?
Elton: 在編程界,Talk is cheap, show me the code是不變的真理。要想推廣Rust,最好的辦法就是使用Rust做一些好的庫或項目。就像Docker之于Go,Rust的重量級應用在哪里?Servo?
愛折騰的Elton
CSDN:你目前認為自己牛的地方在哪里?
Elton: 我不認為自己很牛,在知乎以及其它平臺看到的牛人太多,我覺得自己需要學習的東西太多。我覺得我自己的一個特點就是愛動手,而且保持著對新事物的好奇心。
CSDN: 除了 Rust 是業余愛好之外,在其他方面情況是?還喜歡折騰什么?
Elton: 我還喜歡玩其它各種新的語言還有工具,比如最近站在風口上的Nim語言,還有其它Geek最喜歡玩的Linux、Vim配置,為了改一個配置坐在電腦前一 整天到深夜是常有的事。空閑時還會在Github上看一些關注的人Star的項目,點進去讀讀源碼,讀到精妙的設計跟小伙伴們分享一下。
CSDN:在技術人員/程序員的工作學習中,你是否有什么好的工具?有什么心得和體會可分享?
Elton: 以下僅是個人的一點小心得:
- 政治不正確地講,我覺得先要有一臺MacBook。程序員的工作大多都對著代碼,Retina屏幕對于顯示文字方面實在是無可挑剔。
- 雙顯式器,像寫Rust的時候經常要查文檔,切窗口效率太低了。
- 趁手的編輯器。編輯器最主要的好處就是簡單,寫程序有時候根本不想關注各種的配置方面的東西,一時靈感來時,幾乎沒有延遲地打開,一氣呵成地寫完,編譯通過,提交。我用的是Sublime Text。
CSDN:你認為新人在選擇語言學習時應該注意什么?
Elton: 如果是一個新人想要入門,那么建議選最容易學習的語言,比如Python/Ruby,因為新手在學習的過程中,盡量地減少去關注語言本身或實現相關的細節 會更容易獲得成就感,也容易引起新手學習的興趣。在入門過后,如果是想深入學習,那么建議往C/C++方向走,有利于理解程序底層實現相關的內容,之后可 以考慮學習一下函數式編程語言,如Haskell/Lisp/OCaml等,可以轉變思維方式,防止思維定勢,推薦《七周七語言》這本書,通常學習幾門小 眾語言,了解一下各種不同的編程范式。
但如果只是想趕緊投入到工作中,那么就簡單了,工作要學哪個就哪個。
相關閱讀: 專訪資深程序員莊曉立:我為什么要選擇Rust?
為進一步給Rust愛好者提供溝通、交流的平臺,我們建立了一個微信群,你可以直接向Elton提問,此外,我們也會邀請業內的Rust大牛進群,給大家帶來更多干貨。