在 Go 語(yǔ)言中,就像在任何編程語(yǔ)言中一樣,了解常見陷阱和壞習(xí)慣是編寫干凈、高效代碼的關(guān)鍵。
盡管下面列出的某些做法通常被認(rèn)為是不好的,但在某些情況下它們可以有效地使用。這篇文章旨在提醒大家這些做法的問題所在,并教導(dǎo)如何避免這些陷阱。
讓我們深入探討。
(相關(guān)資料圖)
在 Go 中,init()
函數(shù)是在主函數(shù)之前執(zhí)行的特殊函數(shù)。
“如果在任何包中初始化是如此重要的過(guò)程,為什么在 Go 中
init()
被認(rèn)為是一種不好的實(shí)踐?” —— 讀者
是的,雖然init()
函數(shù)有助于在運(yùn)行核心邏輯之前進(jìn)行初始化,但它們的執(zhí)行順序可能難以理解。這可能會(huì)導(dǎo)致關(guān)于初始化順序的混亂。
如果兩個(gè)模塊互相依賴于初始化并位于不同的包中,則可能會(huì)增加復(fù)雜性并需要額外的代碼添加等待邏輯。然而,這也可能導(dǎo)致死鎖的可能性。
另一個(gè)init()
函數(shù)的問題是它會(huì)使測(cè)試更加困難。因?yàn)樗鼈冏詣?dòng)運(yùn)行,很難控制它們何時(shí)執(zhí)行,這可能使設(shè)置測(cè)試用例和測(cè)試代碼行為變得具有挑戰(zhàn)性。
我遇到了一個(gè)問題,我的服務(wù)從部署狀態(tài)到準(zhǔn)備就緒需要 10 分鐘的時(shí)間。我在主函數(shù)的第一行設(shè)置了斷點(diǎn),但它從未觸發(fā)。
我們不得不調(diào)試所有的
init()
函數(shù),發(fā)現(xiàn)一個(gè)隊(duì)友在一個(gè)“我不記得的包”中使用了init()
函數(shù),從一個(gè)大文件加載了大量數(shù)據(jù)到內(nèi)存中,這導(dǎo)致花費(fèi)了很多時(shí)間追蹤一個(gè)微小的問題。
這與使用單例模式時(shí)可能出現(xiàn)的問題類似,特別是當(dāng)全局變量是復(fù)雜的,包含映射、切片或指針時(shí)。
競(jìng)態(tài)條件(Race condition):當(dāng)使用全局變量時(shí),多個(gè)goroutine同時(shí)訪問全局變量會(huì)導(dǎo)致意外行為。這在Go語(yǔ)言中是一個(gè)很大的問題。
難以測(cè)試:使用全局變量會(huì)使你的項(xiàng)目更具狀態(tài),這意味著當(dāng)你開始單元測(cè)試/集成測(cè)試時(shí),全局變量必須與運(yùn)行main()或生產(chǎn)環(huán)境時(shí)相同。
不夠模塊化且難以重用:難以組織和封裝數(shù)據(jù),因?yàn)槿魏伟蚰K都可以訪問它們。這可能會(huì)導(dǎo)致代碼不夠模塊化,更難以理解,因?yàn)楹茈y確定數(shù)據(jù)來(lái)自哪里以及如何使用它們。
通常建議封裝您的包,使其可以在不影響其他包的情況下移動(dòng)。使用全局變量可能會(huì)使您的代碼更緊密耦合,更難以修改或重用。
錯(cuò)誤是Go編程的內(nèi)在部分,處理它們以優(yōu)雅的方式確保在發(fā)生錯(cuò)誤時(shí)不會(huì)發(fā)生意外情況非常重要。
忽略錯(cuò)誤消息的方法是使用“_”符號(hào),這樣做會(huì)丟棄函數(shù)返回的錯(cuò)誤值,可能會(huì)導(dǎo)致意外行為。
檢查錯(cuò)誤并適當(dāng)?shù)靥幚硭鼈円苑乐钩绦虬l(fā)生崩潰和崩潰非常重要。
忽略錯(cuò)誤處理會(huì)導(dǎo)致生產(chǎn)代碼中出現(xiàn)重大問題,因?yàn)檫@可能使得識(shí)別和修復(fù)錯(cuò)誤變得困難。始終檢查錯(cuò)誤并適當(dāng)?shù)亟鉀Q它們對(duì)于確保代碼的順暢運(yùn)行非常重要。
不僅在Go語(yǔ)言中,許多語(yǔ)言都認(rèn)為使用“goto”語(yǔ)句是一種不良實(shí)踐,因?yàn)樗鼤?huì)使代碼更難理解和維護(hù)。
原因是“goto”語(yǔ)句忽略了代碼流程,使得在不引入錯(cuò)誤的情況下難以理解代碼的不同部分之間的依賴關(guān)系。
這可能會(huì)使得在運(yùn)行時(shí)推理程序的狀態(tài)變得困難,使得調(diào)試和測(cè)試變得更加困難。
使用“goto”可能會(huì)導(dǎo)致錯(cuò)誤數(shù)量增加,使得更難以識(shí)別問題的根本原因。
利用“defer”和“recover”的主要原因是為了防止恐慌。 “defer”甚至可以在發(fā)生恐慌時(shí)執(zhí)行,而“recover”可以捕捉到恐慌,允許更加控制地處理意外情況。
這種使用方式被認(rèn)為是不好的代碼實(shí)踐:
我們使用defer
這種方式,這樣即使readFile()
函數(shù)出現(xiàn)panic,文件也會(huì)被關(guān)閉。此外,這樣做也容易記住在open()
函數(shù)之后立即放置關(guān)閉函數(shù)。
6. 使用太多次的context.Background()
在 Go 中,上下文是最強(qiáng)大的功能之一。當(dāng)正確使用時(shí),它可以作為提供程序、樹流和流控制器。
在進(jìn)行外部調(diào)用(例如數(shù)據(jù)庫(kù)、HTTP 等)時(shí),使用context.Background()
或context.ToDo()
設(shè)置截止時(shí)間或超時(shí)非常重要。如果沒有設(shè)置,當(dāng)用戶過(guò)多且外部服務(wù)沒有及時(shí)響應(yīng)時(shí),可能會(huì)導(dǎo)致您的應(yīng)用程序出現(xiàn)瓶頸。
我通常會(huì)編寫一個(gè)上下文池的實(shí)用函數(shù),其中包括 3 個(gè)函數(shù)來(lái)創(chuàng)建或包裝具有超時(shí)的新上下文:快速(0.5 秒)、中等(3 秒)、慢速(10 秒)。這樣,我就不必一直依賴context.Background()
,并且可以輕松地為每個(gè)調(diào)用設(shè)置適當(dāng)?shù)某瑫r(shí)時(shí)間。
繼續(xù)閱讀
如果你想跟上 Golang 領(lǐng)域的最新動(dòng)態(tài),請(qǐng)關(guān)注我。我會(huì)確保讓你掌握最新情況!
繼續(xù)學(xué)習(xí),享受編程的樂趣,愉快的編碼!
標(biāo)簽:
Go語(yǔ)言的五個(gè)壞習(xí)慣:從錯(cuò)誤中學(xué)習(xí)
刷新歷史!曝中超外援被帶走協(xié)助調(diào)查,郝偉經(jīng)紀(jì)人朋友失聯(lián)多日 每日信息
法爾克:阿森納&巴黎&紐卡有意穆薩-迪亞比,報(bào)價(jià)可能需6000萬(wàn)鎊|天天觀焦點(diǎn)
與大師來(lái)個(gè)碰撞,張藝與北京交響樂團(tuán)樂季音樂會(huì)上演
世界熱點(diǎn)!天天信息:今亮點(diǎn)!世界資訊:當(dāng)前速讀:全球播報(bào):天天短訊!當(dāng)前滾動(dòng):報(bào)道:天天看點(diǎn):自主創(chuàng)新“質(zhì)變”造就新能源汽車排頭兵-當(dāng)前熱議|全球消息-世界熱頭條 世界微速訊-世界速讀_環(huán)球今熱點(diǎn)-世界快報(bào) 世界速讀_全球速訊 今日要聞 每日速看-全球信息|當(dāng)前快報(bào)|全球焦點(diǎn) 天天熱推薦 全球熱門_全球動(dòng)態(tài)_前沿資訊 焦點(diǎn)簡(jiǎn)訊
電影《此生有約》在滬點(diǎn)映,大山里來(lái)的故事質(zhì)樸而珍貴