相信很多人接觸編程都是源于大學(xué)期間的那堂C++語(yǔ)言程序編程,但是這門課卻只告訴了你編程語(yǔ)言是什么,卻沒(méi)告訴你要怎么去熟練掌握編程。所以,不可避免的是許多人在畢業(yè)前夕才發(fā)現(xiàn)雖然學(xué)會(huì)了C++,但是好像卻不知道能干什么,能找什么樣的工作,能去什么樣的公司。所以呢本文就從C++的角度出發(fā),談?wù)勎覍?duì)C++這門語(yǔ)言的理解。
為東臺(tái)等地區(qū)用戶提供了全套網(wǎng)頁(yè)設(shè)計(jì)制作服務(wù),及東臺(tái)網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為網(wǎng)站設(shè)計(jì)、成都網(wǎng)站設(shè)計(jì)、東臺(tái)網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!
咱這回不去談什么復(fù)雜的應(yīng)用場(chǎng)景,也不去聊語(yǔ)言底層的優(yōu)化特性,就說(shuō)說(shuō)在大學(xué)里學(xué)了C++出來(lái)到底能干啥。當(dāng)然了,由于C語(yǔ)言跟C++親密的關(guān)系,咱就混淆一并講了,道理是差不多的。
1 實(shí)驗(yàn)室開(kāi)發(fā)
不敢說(shuō)C++是世界上最好的語(yǔ)言,但C++基本是工科生中的大語(yǔ)言。暫且不說(shuō)計(jì)算機(jī)專業(yè),很多工科專業(yè),比如電信、電氣、通信等專業(yè),基本上正常的學(xué)習(xí)中都會(huì)使用到C++。
都說(shuō)C++兼具面向過(guò)程以及面向?qū)ο蟮奶匦?,既擁有比較優(yōu)秀的運(yùn)行速度,又有良好的大型項(xiàng)目開(kāi)發(fā)能力,那簡(jiǎn)直可以制霸高校實(shí)驗(yàn)室了。當(dāng)然我們知道,另外一門同樣在高校實(shí)驗(yàn)室里與C++不相上下的語(yǔ)言,就是Matlab了。
像我研究生期間就是左手Matlab試探,右手C++優(yōu)化。論文專利什么的就靠這兩種語(yǔ)言雙管齊下。還記得在實(shí)驗(yàn)室里,基本所有的算法都是用C/C++寫的。
最開(kāi)始就學(xué)C++的基本都是老理工男了。就算指針再怎么難理解,虛函數(shù)表再怎么無(wú)情,也磨不滅我們這些工科生對(duì)編程的熱情。
2 后端開(kāi)發(fā)
不過(guò)等到真正要找工作的時(shí)候,就不是那么回事了。聽(tīng)說(shuō)現(xiàn)在由于算法崗已經(jīng)是諸神黃昏了,導(dǎo)致一大批人沖向了后端開(kāi)發(fā)。
而主流的后端開(kāi)發(fā)語(yǔ)言就那么幾種,以Java、C++領(lǐng)銜,Python和Go緊跟其后。作為寫了這么多年的老C++ coder了,哪能不去湊個(gè)熱鬧。
所以呀,學(xué)了C++之后,第一選擇當(dāng)然就是去面試后臺(tái)開(kāi)發(fā)的崗位啦。只不過(guò)我們都常說(shuō)一句話,語(yǔ)言都不是最重要的。那對(duì)于學(xué)了C++想找后端開(kāi)發(fā)的同學(xué)而言,什么最重要呢?
其實(shí)軟件開(kāi)發(fā)工程需要掌握的技能不外乎那么幾點(diǎn),各種經(jīng)驗(yàn)分享和面經(jīng)都已經(jīng)說(shuō)爛了。但是那些只是大的方向,具體涉及到的概念和技術(shù)點(diǎn)非常多,在這里也沒(méi)辦法全部羅列??偟膩?lái)說(shuō),想通過(guò)C++找一份合適的后端開(kāi)發(fā)工作,我建議可以從以下幾個(gè)方面來(lái)提升自己:
一是、扎實(shí)的編程基礎(chǔ)。
這個(gè)基礎(chǔ)扎實(shí)首先意味著你比較熟悉C++這門語(yǔ)言了,知道不同版本的語(yǔ)言特性(比如C++11以及新出的C++20的區(qū)別),對(duì)常見(jiàn)的語(yǔ)言機(jī)制(比如多態(tài)、虛函數(shù)表、模板等)的底層有自己理解。
雖然說(shuō)不看重你用什么語(yǔ)言,但是最起碼你得比較熟練的使用一門語(yǔ)言吧。怎么才算熟練呢,大概C++底層機(jī)制、多線程編程、跨平臺(tái)編程這些你都需要有所了解吧。
除此之外,編程能力的素養(yǎng)還體現(xiàn)在算法思想和數(shù)據(jù)結(jié)構(gòu)的理解上。畢竟程序的基礎(chǔ)就是算法和數(shù)據(jù)結(jié)構(gòu)嘛。所以一些基本的數(shù)據(jù)結(jié)構(gòu),比如鏈表、數(shù)組、二叉樹(shù)、隊(duì)列之類的,還有一些基本的算法思想,比如貪心、分治、動(dòng)態(tài)規(guī)劃等都最好需要好好掌握一下。二是、系統(tǒng)的理論知識(shí)。
這個(gè)就是科班與非科班比較明顯的差距所在了。很多非科班的同學(xué)其實(shí)編程能力很強(qiáng),但是由于沒(méi)有接受過(guò)系統(tǒng)的理論學(xué)習(xí),所以在理論學(xué)習(xí)上會(huì)比較吃虧。而后端開(kāi)發(fā)涉及的東西比較多,從網(wǎng)絡(luò)到性能再到架構(gòu),都需要系統(tǒng)的計(jì)算機(jī)理論來(lái)支撐的。
所以如果連計(jì)算機(jī)網(wǎng)絡(luò)、操作系統(tǒng)、計(jì)算機(jī)組成原理、編譯原理這些書都沒(méi)見(jiàn)過(guò)的同學(xué),需要趕緊買幾本回來(lái)壓壓驚了。
三是、后端基礎(chǔ)。
想去做后端開(kāi)發(fā),起碼得知道后端是什么吧。這就意味著你得知道一些基本的軟件工程、軟件架構(gòu)、設(shè)計(jì)模式等知識(shí)。同時(shí),搞個(gè)后端哪能不懂?dāng)?shù)據(jù)庫(kù)呢,那你不得再學(xué)些諸如MySQL、Redis等數(shù)據(jù)庫(kù)的基本操作嗎?
當(dāng)然到這,可能也就算是個(gè)入門水平。真正上手后端開(kāi)發(fā)的時(shí)候,像微服務(wù)、中間件(Kafka/Zookeeper/Hadoop等)等相關(guān)概念與技術(shù)的學(xué)習(xí)不也得提上日程了嘛。
當(dāng)然對(duì)于校招生來(lái)說(shuō),由于的確是缺少大型的上線項(xiàng)目經(jīng)驗(yàn),所以對(duì)后端基礎(chǔ)的要求不會(huì)太高,更多的是看編程能力和計(jì)算機(jī)理論基礎(chǔ)。不過(guò)倘若是已經(jīng)工作想轉(zhuǎn)行的同學(xué)來(lái)說(shuō),后端基礎(chǔ)還是會(huì)比較看重的。
這三點(diǎn)是在我看來(lái)目前互聯(lián)網(wǎng)公司比較看重的地方,大家可以對(duì)照著反思自己是否具備這樣的能力了。如果還沒(méi)有,可以抓緊時(shí)間好好準(zhǔn)備準(zhǔn)備。
3 客戶端開(kāi)發(fā)
畢竟C++已經(jīng)是一個(gè)很成熟的語(yǔ)言了,所以除了后端開(kāi)發(fā)其實(shí)它還有很多其它的開(kāi)發(fā)崗位可以選擇。自然而然的,就是客戶端開(kāi)發(fā)了。
相信大多數(shù)學(xué)C++的同學(xué)都用過(guò)C++寫桌面軟件吧。那時(shí)候估計(jì)還是用MFC,照著代碼書上敲一遍就能寫一個(gè)比較簡(jiǎn)單的界面了。所以如果不想做后端,完全可以靠C++找一份客戶端開(kāi)發(fā)的工作。
只不過(guò),客戶端也并不容易呀。做客戶端同樣也需要扎實(shí)的編程基礎(chǔ)和計(jì)算機(jī)理論基礎(chǔ),同時(shí)可能還要熟悉Windows/C++編譯鏈接機(jī)制、QT客戶端開(kāi)發(fā)技術(shù)體系、Windows消息機(jī)制等技術(shù)。
所以,假如你學(xué)的是C++,同時(shí)也不在乎業(yè)內(nèi)莫名其名的崗位歧視鏈的話,找一個(gè)客戶端開(kāi)發(fā)的工作也是非常不錯(cuò)的。只不過(guò)相較于后端開(kāi)發(fā),你可能需要重新審視客戶端這個(gè)角色。
前段時(shí)間在golang-China讀到這個(gè)貼:
個(gè)人覺(jué)得golang十分適合進(jìn)行網(wǎng)游服務(wù)器端開(kāi)發(fā),寫下這篇文章總結(jié)一下。
從網(wǎng)游的角度看:
要成功的運(yùn)營(yíng)一款網(wǎng)游,很大程度上依賴于玩家自發(fā)形成的社區(qū)。只有玩家自發(fā)形成一個(gè)穩(wěn)定的生態(tài)系統(tǒng),游戲才能持續(xù)下去,避免鬼城的出現(xiàn)。而這就需要多次大量導(dǎo)入用戶,在同時(shí)在線用戶量達(dá)到某個(gè)臨界點(diǎn)的時(shí)候,才有可能完成。因此,多人同時(shí)在線十分有必要。
再來(lái)看網(wǎng)游的常見(jiàn)玩法,除了排行榜這類統(tǒng)計(jì)和數(shù)據(jù)匯總的功能外,基本沒(méi)有需要大量CPU時(shí)間的應(yīng)用。以前的項(xiàng)目里,即時(shí)戰(zhàn)斗產(chǎn)生的各種傷害計(jì)算對(duì)CPU的消耗也不大。玩家要完成一次操作,需要通過(guò)客戶端-服務(wù)器端-客戶端這樣一個(gè)來(lái)回,為了獲得高響應(yīng)速度,滿足玩家體驗(yàn),服務(wù)器端的處理也不能占用太多時(shí)間。所以,每次請(qǐng)求對(duì)應(yīng)的CPU占用是比較小的。
網(wǎng)游的IO主要分兩個(gè)方面,一個(gè)是網(wǎng)絡(luò)IO,一個(gè)是磁盤IO。網(wǎng)絡(luò)IO方面,可以分成美術(shù)資源的IO和游戲邏輯指令的IO,這里主要分析游戲邏輯的IO。游戲邏輯的IO跟CPU占用的情況相似,每次請(qǐng)求的字節(jié)數(shù)很小,但由于多人同時(shí)在線,因此并發(fā)數(shù)相當(dāng)高。另外,地圖信息的廣播也會(huì)帶來(lái)比較頻繁的網(wǎng)絡(luò)通信。磁盤IO方面,主要是游戲數(shù)據(jù)的保存。采用不同的數(shù)據(jù)庫(kù),會(huì)有比較大的區(qū)別。以前的項(xiàng)目里,就經(jīng)歷了從MySQL轉(zhuǎn)向MongoDB這種內(nèi)存數(shù)據(jù)庫(kù)的過(guò)程,磁盤IO不再是瓶頸??傮w來(lái)說(shuō),還是用內(nèi)存做一級(jí)緩沖,避免大量小數(shù)據(jù)塊讀寫的方案。
針對(duì)網(wǎng)游的這些特點(diǎn),golang的語(yǔ)言特性十分適合開(kāi)發(fā)游戲服務(wù)器端。
首先,go語(yǔ)言提供goroutine機(jī)制作為原生的并發(fā)機(jī)制。每個(gè)goroutine所需的內(nèi)存很少,實(shí)際應(yīng)用中可以啟動(dòng)大量的goroutine對(duì)并發(fā)連接進(jìn)行響應(yīng)。goroutine與gevent中的greenlet很相像,遇到IO阻塞的時(shí)候,調(diào)度器就會(huì)自動(dòng)切換到另一個(gè)goroutine執(zhí)行,保證CPU不會(huì)因?yàn)镮O而發(fā)生等待。而goroutine與gevent相比,沒(méi)有了python底層的GIL限制,就不需要利用多進(jìn)程來(lái)榨取多核機(jī)器的性能了。通過(guò)設(shè)置最大線程數(shù),可以控制go所啟動(dòng)的線程,每個(gè)線程執(zhí)行一個(gè)goroutine,讓CPU滿負(fù)載運(yùn)行。
同時(shí),go語(yǔ)言為goroutine提供了獨(dú)到的通信機(jī)制channel。channel發(fā)生讀寫的時(shí)候,也會(huì)掛起當(dāng)前操作channel的goroutine,是一種同步阻塞通信。這樣既達(dá)到了通信的目的,又實(shí)現(xiàn)同步,用CSP模型的觀點(diǎn)看,并發(fā)模型就是通過(guò)一組進(jìn)程和進(jìn)程間的事件觸發(fā)解決任務(wù)的。雖然說(shuō),主流的編程語(yǔ)言之間,只要是圖靈完備的,他們就都能實(shí)現(xiàn)相同的功能。但go語(yǔ)言提供的這種協(xié)程間通信機(jī)制,十分優(yōu)雅地揭示了協(xié)程通信的本質(zhì),避免了以往鎖的顯式使用帶給程序員的心理負(fù)擔(dān),確是一大優(yōu)勢(shì)。進(jìn)行網(wǎng)游開(kāi)發(fā)的程序員,可以將游戲邏輯按照單線程阻塞式的寫,不需要額外考慮線程調(diào)度的問(wèn)題,以及線程間數(shù)據(jù)依賴的問(wèn)題。因?yàn)?,線程間的channel通信,已經(jīng)表達(dá)了線程間的數(shù)據(jù)依賴關(guān)系了,而go的調(diào)度器會(huì)給予妥善的處理。
另外,go語(yǔ)言提供的gc機(jī)制,以及對(duì)指針的保護(hù)式使用,可以大大減輕程序員的開(kāi)發(fā)壓力,提高開(kāi)發(fā)效率。
展望未來(lái),我期待go語(yǔ)言社區(qū)能夠提供更多的goroutine間的隔離機(jī)制。個(gè)人十分推崇erlang社區(qū)的脆崩哲學(xué),推動(dòng)應(yīng)用發(fā)生預(yù)期外行為時(shí),盡早崩潰,再fork出新進(jìn)程處理新的請(qǐng)求。對(duì)于協(xié)程機(jī)制,需要由程序員保證執(zhí)行的函數(shù)不會(huì)發(fā)生死循環(huán),導(dǎo)致線程卡死。如果能夠定制goroutine所執(zhí)行函數(shù)的最大CPU執(zhí)行時(shí)間,及所能使用的最大內(nèi)存空間,對(duì)于提升系統(tǒng)的魯棒性,大有裨益。