蔡超:入门 Go 语言必须跨越的五个思维误区
你好,我是蔡超,現(xiàn)在是Mobvista 技術(shù)副總裁,前亞馬遜(中國)首席軟件架構(gòu)師,極客時間《Go語言從入門到實戰(zhàn)》視頻課程的作者。
在2018年的QCon北京全球軟件開發(fā)大會上,我做了題為《講給 Java / C++開發(fā)者的Go高效編程》的主題演講,會后跟大家交流,發(fā)現(xiàn)許多人對Go語言的學(xué)習(xí)有需求和熱情。但大家的普遍問題就是:不知道該如何高效的入門 Go語言,尤其是有編程基礎(chǔ)的開發(fā)者,一不小心就會陷入思維的誤區(qū)。
因此,今天我就來梳理一下Go語言入門學(xué)習(xí)的過程中,你容易產(chǎn)生的五個思維誤區(qū),幫你掌握在Go語言與其他編程語言的不同之處。
一、重新思考面向?qū)ο蟪绦虻脑O(shè)計和實現(xiàn)
首先,你要先理解Go語言面向?qū)ο缶幊淌蔷哂刑厥庑缘摹.?dāng)然,“Go是不是支持面向?qū)ο蟆斑@本身就是一個值得思考的話題,官方文檔給出的答案是“Yes and no” 。雖說 Go 語言中是有類型的存在,也允許面向?qū)ο蟮木幊田L(fēng)格,但卻沒有類型層次結(jié)構(gòu)。
Go語言中沒有對類型繼承提供支持,而是通過復(fù)合來進行擴展,并通過類型嵌入來簡化復(fù)合的使用。很多人會把類型嵌入看成是Go中的繼承機制,但是類型嵌入并不支持最基本的繼承特性:
子類替換
方法重載(override)
Go語言中的接口機制與其他語言截然不同,實現(xiàn)接口的類型完全不依賴于接口定義。接口作為方法簽名的集合,任何類型的方法集中只要擁有與之對應(yīng)的全部方法,就表示它實現(xiàn)了該接口。只有深刻理解這些,才能更好發(fā)揮Go的生產(chǎn)力特性。
不支持繼承,特殊的接口類型,這些都會要求我們重新思考設(shè)計和編程實現(xiàn)。
戳此可獲取:Go語言官方文檔
二、改變傳統(tǒng)GC(垃圾收集器)語言的思維模式
Go是一個非常特殊的語言,即追求簡單性又追求高效率,Go既內(nèi)置支持GC(垃圾收集器),又支持指針對內(nèi)存的直接訪問。其他支持GC的語言,比如在Java中,由于希望對開發(fā)者可以屏蔽內(nèi)存管理,所以語言中沒有提供指針的直接訪問。為了提高數(shù)據(jù)訪問和傳遞的效率,編程語言根據(jù)不同的情況,通過約束采用值傳遞或引用傳遞,來減少數(shù)據(jù)復(fù)制。
而Go比較簡單地統(tǒng)一采用值傳遞,但提供指針機制,因此用戶可以自己來選擇數(shù)據(jù)的傳遞方式,要引用傳遞時可以通過傳遞指針來完成。
所以在編碼時,你要考慮充分指針,提高數(shù)據(jù)訪問效率,減少內(nèi)存復(fù)制并編寫GC友好的代碼。
三、重新思考程序的錯誤處理機制
Go語言的錯誤處理機制中既不支持現(xiàn)在主流的異常模式,同時也與傳統(tǒng)的C程序通過返回值返回錯誤狀態(tài)不同,Go語言支持返回多個值,可以同時返回結(jié)果和錯誤狀態(tài)。
- 以下是Java語言示例:
- 以下是Go語言示例:
Go的error處理方式一直以來都是爭論的焦點,很多開發(fā)者認(rèn)為Go的錯誤處理機制似乎回到了70年代,使得錯誤處理代碼冗長且重復(fù)。而Go的設(shè)計者則認(rèn)為try-catch-finally的結(jié)構(gòu)導(dǎo)致異常處理與控制流程的耦合,從而使程序結(jié)構(gòu)發(fā)生了混亂。
Go的設(shè)計者當(dāng)初選擇返回值這種錯誤處理機制,而不是try-catch這種機制,主要是考慮到前者適用于大型軟件,后者更適合小程序。因此,程序變大的時候,try-catch會讓錯誤處理更加冗長繁瑣,也就容易出錯。try-catch-finally會慫恿程序員標(biāo)注過多普通錯誤,諸如打開文件失敗之類的異常,使得程序更加繁瑣。
這就決定了你必須重新思考錯誤處理的編程模式,因為這樣的代碼是Go語言中非常常見的。
四、思考和學(xué)習(xí)使用CSP并發(fā)模型
與主流語言通過共享內(nèi)存來進行并發(fā)控制方式不同,Go語言采用了CSP模式。這是一種用于描述兩個獨立的并發(fā)實體通過共享的通訊 Channel(管道)進行通信的并發(fā)模型。很多使用過Erlang等基于Actor模式的程序員,會誤認(rèn)為Go和這些語言的模式是一樣的。
而實際上,Go的CSP模式與常見的Actor模式(如:Erlang語言就采用了Actor模式)也有不少差異,例如:
- 和Actor的直接通訊不同,CSP模式則是通過Channel進行通訊的,更松耦合一些;
- Go中channel是有容量限制并且獨立于處理Groutine,而如Erlang,Actor模式中的mailbox容量是無限的,接收進程也總是被動地處理消息。
所以,要用好Go語言,一定要思考和學(xué)習(xí)使用CSP來高效的實現(xiàn)我們常見并發(fā)任務(wù)。
五、理解Goroutine的調(diào)度機制
Goroutine 是Go語言的招牌特性之一,較之線程是非常輕量級的。但是,如果你不了解其中的機制,僅僅按照線程的套路來使用,就發(fā)揮不出來Goroutine的優(yōu)勢,甚至還會導(dǎo)致很多性能問題。
Goroutine有著和Java線程完全不同的調(diào)度機制,Java線程模型中線程和KSE(Kernel space Entity)是1:1的關(guān)系,一個用戶線程對應(yīng)一個KSE。而Groutine和KSE是多對多的對應(yīng)關(guān)系。雖然,Groutine的調(diào)度機制不如,由內(nèi)核直接調(diào)度的線程機制效率那么高,但是由于Groutine間的切換可以不涉及內(nèi)核級切換,所以代價小很多。
CSP并發(fā)模型、Goroutine的調(diào)度機制是Go語言入門學(xué)習(xí)的過程中的重點和難點,我會在《Go語言從入門到實戰(zhàn)》進階篇中進行詳細(xì)的講解,敬請期待。
拓展閱讀:
5個步驟,編寫你的第一個 Go 程序
總結(jié)
以上是生活随笔為你收集整理的蔡超:入门 Go 语言必须跨越的五个思维误区的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: postman模拟登录接口
- 下一篇: 瞎说系列之Object.assign入门