專訪輪子哥:我在微軟「造輪子」,一不小心成了知乎大V

陳梓瀚Vczh,在網絡上,大家可能熟悉他在知乎的外號——輪子哥。而在現實中,他的名字就印在久負盛名的C++經典教程《C++ Primer 第五版》的封面上,因為他是這本書的審校之一。

他常年利用閑暇時間開發(fā)C++圖形界面庫GacUI。這是一款在架構上跨平臺、支持控件與模板分離、靈活的數據綁定以及全面支持MVVM模式的C++ GUI庫。

如今,他在西雅圖微軟總部為Office開發(fā)基礎組件庫,也就是專業(yè)「造輪子」,無論工作還是閑暇,他都樂衷于此,知乎「輪子哥」的外號也是因此而來。

在知乎上,除了為大家解答技術問題以外,他還關心國內外的時事以及網友們的生活情感問題,并為知乎情感話題不設優(yōu)秀回答者表示遺憾。

今天圖靈訪談就來聊聊他與編程的故事。

文?|?李冰

?我的大部分編程書都是在上廁所時看的?


他的生活準則很簡單:為自己喜歡的事投入時間。

于他而言,編程并非一份職業(yè)或者事業(yè)。他曾說:「一日不編程,食肉無味。喜歡便用心鉆研,然后十幾年不曾改變。而一切剛開始的那個時候,他沒有想這么遠,就是覺得很有意思。

「上小學的時候,學校明明就沒有計算機,不知道為什么有幾本 DOS 的教材,不過我還是拿來看了。然而家里也沒有電腦,所以也只能當圖書看。那個時候對計算機唯一的概念就是去表哥家里看他操作 Explorer,我對這些東西產生了好奇。

「后來上了初一,在我要求購買電腦之后,父親讓我用壓歲錢按人頭入股,買了一臺聯(lián)想天禧 2000。盡管我壓歲錢的存折其實就在父親手里。

「聯(lián)想自帶了個幸福之家軟件,一開始我就擺弄那些東西,覺得很好玩。后來我試圖自學怎么使用 Office,但當時打開了 Excel 之后一臉懵逼,根本不知道那個是什么再后來,我在書店里看到了 PowerPoint 和 FrontPage 的教材,就開始學著瞎搞 HTML,剩下的時間就玩親戚和同學跑來我家里裝的游戲。

「恰巧,具有前瞻性眼光的廣東汕頭華僑中學,在初一開了計算機的課,學習如何用 DOS 和 Win 3.2,后來在初二又開了 QBasic + Visual Basic 5.0?的課。我一直都習慣開學的時候就把理科課本先給看了,于是我就開始自學。

「初中時我的成績不怎么樣,雖然我未來考進了華南理工大學,但是那個時候父母還在擔心我能不能上一本。然而我對這種事情毫不關心,人為什么要做自己不喜歡的事情呢?除非被父母打了。買完電腦不久,父親就限制我只有周末才能使用。

所以我大多時候是在紙上學習 QBasic 的。我花了大概一個星期,就把 QBasic 半個學期的東西都給學了。書里的內容很少,只教了怎么聲明變量,聲明函數,還有條件和循環(huán)語句等。

「這時我接觸第一臺電腦只有半年多,很多軟件都用不利索,系統(tǒng)操作也只會簡單的打字或畫圖,當年的 Windows 還自帶 QBasic,所以我學習編程跟學習計算機的使用是同步的。

「一個星期之后,我寫出來的第一個程序,就是輸入數字、回車、數字、回車,再加上操作符,然后算加減乘除,寫了從1加到100這種東西。然而這種簡單的練習只能讓我學會語法,但是我經常在需要什么語法的時候都沒反應過來,還發(fā)生了像‘人肉展開循環(huán)’這種滑稽的事情。

「QBasic 的課本看完了,我就接著看 VB5 的課本。后來為了找資料,我經常往書店里面走。我買到的第三本書就是《Visual Basic 高級圖形程序設計教程?》。這本書其實很難得,不僅涉及了很多我初二時還沒學過的數學知識,而且還教了很多圖形和圖像的算法,從渲染分形圖,到掃描曲線,到抗鋸齒,到如何把真彩色圖片降級到 256 色的算法,最后甚至連光線追蹤引擎也說了。

「我一開始覺得里面的圖片很漂亮就買了,覺得 VB6 竟然不僅僅能畫窗口,還能編程弄出圖片來,很有意思。當然看懂是不可能馬上就看懂的,這本書我一直翻到了大學才看完,期間甚至還掉進過廁所里。

大學時期的作品

「因為中學的那段時間,周一到周五就只有上廁所和睡覺前躺著可以看自己喜歡的書,剩下的時間要么就上課,要么就做作業(yè),忙得很。我買的大部分編程書都是在上廁所的時候看的,現在想想覺得自己真是太勤奮了。

「當然光看書學習也是不行的,所以我還經常在一些論壇上跟人家互相交流,特別是當年的網易社區(qū)上有一個 VB 板塊。那個時候國內的計算機行業(yè)也不發(fā)達,大多數上論壇的人都是菜鳥,我學著學著發(fā)現,我也可以回答別人的問題了。

「那個時候上網很貴,撥號了還會導致家里電話打不通,所以我也從不閑逛。我在 VB 板塊上經常做的事情就是問問題,或者回答別人的問題,還有跟網友互相交換自己的代碼,互相學習、評價什么的。

「2000 年,谷歌和百度也就剛開始,當年最有名的就是搜狐的搜索引擎,但是其實也沒什么用,什么網站有什么東西都是靠網友相傳的。大家互相聊天的時候就會知道一些信息,只能是這樣子來獲取資料。至于身邊的同學嘛,所有人都對編程不感興趣,整個班就只有我一個人在弄這個,所以跟真人交流什么的,那是不存在的?!?/p>

一路獨自摸索,當然會遇到不少困難。然而,一旦把時間的刻度拉長,以十年為尺,這些算什么彎路?以自己的方式堅持下去就是捷徑。

他說:「挫折當然是有的,但是我學習編程的出發(fā)點,就跟大家打籃球一樣

「失敗了繼續(xù)找書找資料,實在不行就算了嘛,那么多程序可以寫,為什么非要死磕這個呢?所以當年雖然有很多嘗試都是失敗的,但是我覺得無所謂。盡管如此,有時候‘算了’之后的一段時間,偶然給我看到合適的資料,就又學了,還覺得挺驚喜的。

「大家打籃球,學 NBA 的球員花式傳球投籃扣籃,不也經常失敗嘛。因此就不打籃球了嗎?玩紅警的時候被 AI 屠殺了,玩 RPG 沒打過 boss,就不玩了嗎?當然是不會的。我對待編程就是這個態(tài)度。編程本身就可以給我?guī)砜鞓?,所以結果已經不重要了。

我覺得自學對我的幫助,就是我變得特別有耐心。尋找知識困難,是從一開始就有的,我已經習慣了。程序越寫越大,調試起來花很多時間,這個也已經習慣了。

「寫代碼最重要的就是靜下心來,愿意為學習編程花費大量的時間。

「我也經常通過 re-engineer 別人的東西來學習,看見一個什么東西就想自己寫一遍。在這個過程中,不僅可以深刻地了解里面的道理,而且你經過親自吃屎,你就能知道為什么作者要這么做而不要那么做,甚至你還可以發(fā)現可以改進的地方。當然這也需要大量的時間?!?/p>

瞎編個故事,先把RPG游戲搞起來!


編程界有句老話:不要重復「造輪子」。

而他正相反,寫代碼的這些歲月里,他將絕大部分時間都花在了「輪子」上。

在大學,他開發(fā)了渲染器、腳本引擎、圖形界面、編譯器等。去微軟工作后,他申請了兩次調動,現于Office組專業(yè)造輪子。工作之外,他常年開發(fā)自己的 GUI 庫 GacUI,這些年,他造的輪子越來越精深,隨著知識和經驗不斷累積,他也越來越游刃有余。

有人很不理解,既然已經有了現成的工具,為什么還要花大把時間再造一個?

一方面,他在不斷借鑒與改進,致力于使解決問題變得更容易;另一方面,動手實踐是學習的最好方式。最重要的是,對他而言,編程就是以自己的方式創(chuàng)造好玩的東西。

故事的起點,要回到他高二寫的那個一萬多行的 RPG 游戲。

其實我初三就嘗試過做游戲,那個時候用 Picture 控件一個一個拼圖,理所當然地失敗了。

「后來我學會如何不在 Picture 控件里畫圖,也慢慢找到 VB 寫 module 的感覺,就開始能做一些小游戲了,代碼的組織雖然不能說好,起碼不能說沒有了。高中改用 Delphi,還學習了 Windows API 和 VCL 的一些操作,我終于搞明白如何直接畫進一個指針里了,也終于可以快速刷新畫面了。這就為我的游戲打下了基礎。

「那個時候我就想:來做一個 RPG 吧。

「事情的起因還是初中泡論壇的時候,網友分享了他們用 C++ 寫的 RPG 給我。我覺得既然他們可以,那我也可以啊。所以經歷了若干次失敗之后,甚至到了我的注意力從 VB 轉移到 Delphi 之后,我都一直記著這件事情。在終于學會了足夠多的技術之后,我就想把它做出來。

「所以我直接跟當時那個小組把素材給討了過來,瞎編個故事,然后就搞起來!

「記得立項的時候是高一的勞動節(jié),我已經學習編程兩年多了,也已經熟悉了面向過程編程,也慢慢理解了為什么大家要把一些功能相關的函數分組放在文件里面,于是我就開始規(guī)劃這個代碼要怎么寫。

「當時直接想到的就是,一個 RPG,要有 KV-store,要有 UI,要有腳本,要有 2D 的渲染引擎,還有一些其他部分。我可以挨個完成,做完了才來做地圖編輯器,然后再做游戲本體,最后拿地圖編輯器來寫腳本編故事,游戲就可以跑起來了。

「RPG 用到的腳本引擎長得就像帶有控制流語句的匯編語言。當時設計的時候,考慮到一個游戲經常要畫對話框,讓玩家選選項,但是游戲循環(huán)本身又不可能讓你的腳本引擎卡死,所以我想了一些辦法,最后專門給腳本引擎添加了一個斷點功能。

「游戲跑到了那些需要暫停的命令里,腳本引擎當場就退出了,然后游戲會根據留下來的命令的‘尸體’來做相關的操作,操作完了再讓腳本引擎從當初停下來的地方接著跑。

做這些東西的時候,數據結構、編譯原理什么的根本聽都沒聽過,我只從一本 VB 的游戲開發(fā)教材里面,學習到了鏈表,加上 Delphi 自己帶的一些容器,剩下的東西都是在上面搭建的。因此當時做出來的 UI 引擎還挺搞笑的,控件只能套兩層,因為我沒有樹這個概念,更別提怎么用代碼表達了。

大學時期的作品

其中,我覺得最困難的部分,就是游戲要如何快速刷新。那個時候我試圖學習DirectDraw失敗了,所以我就用GDI+DIB搞。當時我的電腦算是不錯的了,但也很慢,根本沒辦法讓我每一幀都完全從頭開始畫,貼到窗口上,最后還能保持60fps。

如何在游戲往前走一幀的時候,只畫上一幀的圖需要改的部分呢?最后我想到了一個辦法,每次游戲修改地圖內容的時候,我都會留下一個flag,代表這里動過了。玩家的角色還會移動,所以我直接把上一幀的整幅圖跟著移動的方向復制一遍。

「這樣復制還是挺快的,DIB都是可以拿到指針的,直接移動指針的數據就可以了。復制完,邊緣就會留下一些要修補的部分,再加上我打過的所有flag,全部按格子的分列先分組,再看每一組里面有多少格需要更新,最后分批填上去。

為什么要分列呢?因為 2D 的 RPG 地圖的遮擋關系是上下的,而不是左右的,分列是為了按正確的遮擋關系畫圖。

「設計是美好的,但是游戲人物是不跟地圖的格子對齊的,所以最后搞得很復雜,我寫了好多天才把 bug 調完,花了很大精力。

「這一萬多行代碼我大概寫了三個月,然后花了半年編故事畫地圖寫腳本,終于在第二年過年的時候 release 了。那一刻我覺得我完成了一項壯舉,就跟我現在練了兩年終于能深蹲150kgX10次/組的感覺很像。

「現在回想起來,日后的很多習慣,都是由我開發(fā)這個 RPG 所領悟到的東西慢慢發(fā)展出來的。

「譬如說,后來我回頭看我的代碼,發(fā)現很多函數都是圍繞著一個數據結構展開的,這不就是類嘛我怎么就都用函數來寫呢?于是我就開始大量使用類來編程。

「譬如我推崇的測試驅動開發(fā)。我做 RPG 的時候雖然不懂什么叫測試,但也是從小模塊開始寫,寫幾個窗口讓我可以人工測試小模塊的代碼,然后慢慢搭起來的,并沒有選擇一上來就寫游戲本體。因此后來我接受測試驅動開發(fā)的時候,覺得這簡直就是理所當然的事情啊,沒有任何理由不這么做。」

到了大學,他才開始系統(tǒng)性地學習計算機的理論知識,同時與過去的經驗相互印證,又不斷產生新的領悟。

?我轉C++的契機?因為Delphi跪了?


C++是一門神秘的語言,業(yè)界流傳著許多它的傳說。

有人說自己14天就掌握了C++;有人講述自己3個月從入門到放棄;有人說自己有10年經驗,卻只算有一定的C++基礎,更不敢談什么精通……

而他與 C++?的故事也很長。

「我轉C++的契機完全就是因為我大一時Delphi跪了,所以并不是我喜歡C++才用C++的,開發(fā)游戲不用Delphi就只能用C++,實在是沒得挑了。

「不過我初三的時候就在學習C++了。那時候我在看《Visual Basic高級圖形程序設計教程》,想跟網上的人交流,但是我發(fā)現這些搞圖形的怎么全都用C++?很郁悶。所以為了看懂他們的代碼,然后抄成VB,我就去學習C++了?!?/p>

可是,他在書店里找到的資料是 MSDN 里語法手冊的影印版,而語法手冊不是按照學習順序來組織內容的,對初學者非常不友好。

當年的他對此一無所知,花了很長時間才看完了第一遍。看的時候他想:「怎么C++這么難,才學習怎么寫函數,接著就講template class的東西?」這當然也不可能實踐了,只能干看。但他從頭到尾看了兩三遍,竟然真的能看懂一些了。

不過C++的強大注定了故事不會這么簡單??炊淮砟軐?,上大學前,他的C++水平是「只讀」的;能寫也不等于會寫,上大學后,他學會了用C++的語法寫Delphi。

然而,就像鋪墊會等來轉折,那些Delphi的日子,他研究它的內部原理和實現細節(jié),這幫助了他理解和掌握C++;后來,他又遇到了函數編程語言Haskell,領略了語法邏輯之美,從另一種角度審視和深入C++。

大學時期的作品

如今,他越來越得心應手,C++的強大帶給他的是自由,而不再是束縛。

「我現在很喜歡C++,因為C++表達能力非常強,而且能實踐type-rich programming,意思就是說,你要把函數的邏輯表達在類型上。如果將來函數本身做出了breaking change,那么你的函數簽名也要有breaking change,就可以盡量跟Haskell一樣,通過增加編譯通過的難度,來減少debug的需要,跟測試驅動開發(fā)(TDD)異曲同工。

「現在我也很喜歡TypeScript,理由是一樣的。我以前非常討厭JavaScript,因為JavaScript沒辦法type-rich programming,所以直到TypeScript 2.9誕生了之后,我才開始投入時間。

「好的語法對開發(fā)效率的幫助是很大的,這直接決定了你開發(fā)庫的時候,API 的設計是否能準確簡潔地表達業(yè)務邏輯,從而又決定了使用這些庫的代碼的質量。所以一段代碼的質量,排除程序員本身水平的因素以外,完全是由語法決定的。

「自從沒事擺弄了很多語言之后,現在學起新的來也很快了。我一般都會從‘作者為什么要這樣設計’出發(fā),但事實上很多語言是他們拍腦袋搞出語法的,這就導致我只想用我喜歡的那幾門語言(目前是C++、C#和TypeScript)來開發(fā)程序,受不了別的?!?/p>

?編譯時刷知乎,一不小心成了大V?


高考之后要干嘛,瘋玩?沒錯,但他的「瘋玩」和別人不太一樣。

他解放了!再也沒人說編程會耽誤學習和考試,再也不用躲在廁所里偷偷看編程書了。

高考后的暑假,他愉快地將高三時開發(fā)的簡易 Pascal 解釋器重新整理,寫了幾十頁的設計方案,打印出來帶到了華南理工大學。那個時候,數據結構他只會用鏈表,而且編譯原理也好,設計模式也好,都還沒聽過。

他選的專業(yè)是軟件工程,剛入學,他就把那沓紙給班主任陳健老師看,她看完什么也沒說,給了他一本編譯原理的課本。

他用里面的知識做了第一個真正意義上的腳本引擎,參考了Java語言的一些簡單部分,還添加了一個編譯時自動把模板參數都改成Object類型的語法。后來Java添加了泛型功能,竟然也是這么干的。

大學的課堂里、圖書館里,他流連在那些抽象的概念與理論之間,回顧自己摸索時趟過的泥坑,很多疑惑豁然開朗。他一邊把高二RPG游戲中的那些工具改進或重寫,一邊開始更深入的技術探索。

大學時期的作品

大三,他照著 JavaScript 做了一個沒有糟粕部分的動態(tài)腳本語言。也是那年,陳健老師找老同學幫他投了微軟的實習簡歷。

終于,他的編程水準要經受外界的第一次考驗了。

在電話面試中,他與對方聊了自己做的那個動態(tài)腳本語言,還就一些數據結構和框架設計的問題進行了熱情洋溢的討論。沒過幾天,他就收到通知前往上海面試。

現場面試時,盡管由于緊張出現了失誤,但憑借扎實的基礎與能力,他順利進入 WCF Tools 小組實習。

白天實習,晚上,他利用空余時間完成了一門純函數式語言,后來成為了他的畢業(yè)設計。畢業(yè)前的幾個月,他又完成了一個簡化后的?C 語言的編譯器,可以在內存中生成 X86 機器碼并馬上執(zhí)行。

上中學,高考,上大學或者去實習,無論外界的環(huán)境如何變化,他執(zhí)著于給自己的編程世界添磚加瓦。

2008 年10月,次貸危機波及了微軟上海。11月,他的實習結束了,而等待他的是收緊的轉正名額。盡管如此,他成功通過了五輪艱難的面試,正式成為微軟的一員,開始了他的職業(yè)生涯。他從微軟上海,到微軟亞洲研究院(MSRA),再到微軟西雅圖總部工作至今。

編程陪伴他的歲月,決定他的職業(yè),塑造了他的生活,甚至性格的某些部分。讓他安靜下來,不在乎外界的雜音,投入于喜歡的事,并且選擇自己喜歡的生活方式。

工作后,從 2013 年開始,他的時間支出表上增加了一個大額新項目:刷知乎。迄今為止,他憑借獨特的個人風格,在知乎共收獲 2773k 贊同,擁有 805k 關注。

除了程序員外,知乎大 V 成為了他另一個身份。一方面,這意味著大量來自外界的關注;另一方面,如果用時間來劃分地盤,知乎以碎片化的優(yōu)勢積少成多,地位直追編程。

面對這些變化,他的心態(tài)很平穩(wěn)。

他說:「上面有提到,我從一開始就是泡在論壇上的,后來一路換過來,最后到了知乎。我覺得跟我互動的人多了,完全就是因為現在上網便宜了,泡在網上的人多了,這是很自然的。

「至于說寫代碼的時間減少的這個問題,我更多的是覺得,現在精力不如當年了。以前我真的可以做到平均每天 8 小時寫代碼,但是現在寫不動了,連續(xù)寫那么久代碼會覺得頭腦發(fā)暈想吃飯。

「不過一天 24 小時又不會因此縮短。我剛好還是一個睡眠時間不長的人,每天睡 6 個小時,第二天滿血復活,所以迫切需要很多事情來填補活著的這段時間。我覺得休息的時候有個知乎可以刷,挺好的。刷膩了我就玩游戲,跟老婆和網友們到處找新的館子吃,生活非常充實。

「其實并沒有緊迫感,自己的項目又沒有 deadline,但現在胃口大了,開發(fā)什么都很久,恐怕壽命是不夠用了。想想到時候快死了,腦子里還有很多東西沒有親手試一試,覺得人生最慘的事情莫過于此了。」

他坦然接受生活帶給他的每種可能,踏出自己的代碼國度,在外界與自我之間尋找一種平衡,但他對編程的熱情從未改變。

大一,他就用OpenGL寫了個游戲用的GUI庫當C++的大作業(yè);大二,他開始設計一個基于OpenGL 的、面向軟件開發(fā)的GUI庫;大三重新學習如何封裝包含Vista新功能的Windows API;大四學習如何開發(fā)一個control template與control分離的新的GUI框架。到了開始工作之后,知識基本準備好了,他的GacUI終于立項了

GacUI是一款在架構上跨平臺、支持控件與模板分離、靈活的數據綁定以及全面支持MVVM模式的C++ GUI庫。GacUI在Windows上使用DirectX進行硬件加速,并且下一個版本計劃支持macOS以及wasm。

另外,開發(fā)GUI之余,他在腳本引擎方面也在不斷地學習和進步。大一結束后他實踐了垃圾收集器;大二實踐了動態(tài)語言;大三實踐了帶惰性計算和類型推導的函數式語言;大四實踐了到機器碼的編譯。

這些項目跟隨他從大學畢業(yè)到工作,直到現在,不僅記錄了他技術的進步,熔鑄了他的理念,并且促使他不斷地向遠方探索。為了將GacUI移植到瀏覽器,他的學習范圍還延伸到了前端領域。

Github提交圖?? 來源:https://github.com/vczh-libraries??

「關于GacUI,我的設計理念曾經有很多,但是凡是跟XAML不一樣的,最終都證明不如XAML,所以現在就是跟XAML無限靠近了。我做出的唯一改進是關于Data Binding的這部分。XAML只支持非常有限的語法,你自己要干點什么復雜的都要MVVM+DataBinding+resource+converter一套搞下來,煩得要命。所以GacUI支持你用任意表達式來做單向binding。逆一個表達式實在是太難了,所以我沒有支持雙向binding,雙向嘛,不就是單向寫兩遍。

「以后可能會用GacUI來寫一些小IDE吧,做做intellisense啥的,順便把代碼共享進VSCode當插件。我覺得很有意思。

「在開發(fā)GacUI的過程中我還接觸了很多東西,譬如說如何給C++做反射和讀C++代碼里的注釋生成文檔,這個我就做了好幾遍,每一次都比前一次有了巨大的改進。就算是網站本身,我也通過開發(fā)它學習了一些內容。之前我還想過要把GacUI搬到瀏覽器里,現在我想用wasm來實現,但是之前我竟然覺得可以用JavaScript重新實現一遍,所以學習了很多HTML 和CSS的排版知識。

「一個人親自開發(fā)一個復雜的東西,可以得到探索其他領域的動力,我覺得這已經成為了我的習慣?!?/p>

最后,他總結說,自己學習編程只有一個秘訣。

「學習編程,只要你能在過程中感到快樂,那所有的問題都是不存在的,你就會不斷地把時間投入到學習編程中去,時間積累夠了再怎樣也熟能生巧了。所以我一直都說,平均每天寫 8 小時代碼,從大一做到大四,不可能學不會的。有些人曾經提出反對意見,但歸根結底都是因為他們不認為編程是這個世界上最有趣的事情?!?/p>

編程時間線

2000年?初一

他第一次接觸計算機和編程

2004年 高二

他發(fā)布用Delphi寫的RPG游戲

2006年?大一

他用OpenGL寫了個GUI庫當C++的大作業(yè)

他實踐了垃圾收集器

2007年?大二

他開始設計一個基于OpenGL?的、面向軟件開發(fā)的GUI庫

他實踐了動態(tài)語言

2008年?大三實習

他照著?JavaScript?做了一個動態(tài)腳本語言

實習時,他還完成了一門純函數式語言

2009年?畢業(yè)轉正

畢業(yè)前,他完成了一個簡化后的?C?語言編譯器

2011年10月

他的C++圖形界面庫GacUI項目正式啟動

2012年3月

GacUI項目開源了

2012年7月

他為GacUI做了一個網站

2014年

GacUI主要功能完成

2017年

GacUI現在的架構完成

2018年9月

他開始為了GacUI的文檔造含C++編譯器前端的網頁生成器

2019年8月

他將GacUI的網站gaclib.net重寫

往期訪談

寒冬 winter:代碼無捷徑,只怕有心人

C++之父Bjarne?Stroustrup:?簡單的表述方式才是最優(yōu)的方案

“龍書”作者Jeffery Ullman:相信你自己,自由地思考

《七周七并發(fā)模型》作者Paul Butcher:這是一個激動人心的編程時代,也是一個帶有很大不確定性的時代

想看看輪子哥的GacUI嗎?戳一下這里!

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容