今天是Golang專題的第二篇,我們來看看Go的語言規範。
在我們繼續今天的內容之前,先來回答一個問題。
有同學在後臺問我,為什麼說Golang更適合分散式系統的開發?它和Java相比有什麼優勢嗎?
其實回答這個問題需要涉及很多概念,比如作業系統當中關於程序、執行緒、協程等很多概念。我們將這些內容進行簡化,舉一個最簡單的執行緒的例子。我們來寫一段在java當中實現多執行緒的例子:
我們再來看看Golang:
這麼一對比是不是簡單很多?
Golang的語言規範大家都知道程式設計師最大的分歧之一就是花括號到底應該寫在哪一行,有另寫一行的,也有跟在迴圈體後面的。這兩撥人分成了兩個流派,彼此征戰不休,也衍生出了許多段子。
為了統一風格,很多語言對程式碼風格做了規範。比如Python就去掉了花括號,而使用空格來進行程式碼縮排。然而不幸的是,有些人縮排用四個空格,也有些人用tab,這雙方又形成了陣營,彼此爭吵不停……
也許Golang的開發者曾經飽受程式碼風格爭吵的苦惱,所以Golang做了一個劃時代的事情,它嚴格限制了程式碼風格,強行統一大家都必須使用同一套風格,否則就分分鐘報錯給你看。所以在我們進行具體的語法學習之前,先從語言規範開始,否則等我們後面養成了不好的習慣再想要改正就會成本很高。其實改正程式碼風格是一件很難的事情,老實說我的程式碼風格不是很好,總是使用一些cur、pnt、node、u、v這種簡單的變數,這也是當年打acm留下來的習慣,想改一時半會蠻難的。所以大家一定要在初期就養成好習慣,壞習慣就留給我一個人吧(大霧)。
package規範Golang的語言規範很多,涉及的面很廣,有些我們暫時用不到,我們先挑基礎的說。首先是package規範,對於package來說它的名字應該和目錄保持一致,採取有意義的包名,不要起一些別人看不懂的名字。比如test、unit這種,並且不能和標準庫衝突。
其次是我們在引包的時候,需要注意不要使用相對路徑,而應該使用絕對路徑。
當然我們可以裝一個goimport工具,幫助我們自動引包。但是自動引包也會有坑,尤其是當目錄下存在兩個包名稱一樣的時候,有可能會引入錯誤,需要我們自己留意。
程式碼風格規範Go語言當中規定了我們應該使用駝峰標準來命名變數,不能使用_。在Go當中首字母大寫表示結構體中的變數或者是包中的函式public,如果是小寫則表示是private,這一點尤其需要注意。剛開始寫go的時候都會很不習慣,因此踩坑是常有的事。
golang當中是有常量的,golang當中的常量一樣用駝峰標準,首字母大寫。比如我們起一個常量叫做app_env,表示當前app執行的環境,我們必須要這樣定義:
const AppEnv = "env"
另一點是Golang的設計者認為行尾加上分號毫無必要,所以在編譯器當中添加了會在行尾自動加上分號的功能。所以我們可以加也可以不加,但是一般認為沒有必要這麼做。所以普遍來說,除了在迴圈體或者是判斷條件當中,我們一般是不寫分號的。當然也有特殊情況,比如你想要把多條語句寫在一行的時候:
var a int; var b float;a = 3; b = 3.2;
當然還是一般不推薦這麼幹,建議分成多行,更加美觀。
另外一點是golang當中所有的變數和包都必須用上,不允許定義沒有使用的東西,否則也會報錯。也就是說嚴格限制了我們寫程式碼時候的謹慎。不能隨意申請用不到的變數,大多數語言當中沒有這樣的限制,但是golang當中做了限制,所以我們寫程式碼的時候要小心。
另外一點是關於花括號,在golang當中嚴格限制了花括號寫在當前行,而不是另起一行。
從上面這個例子我們還可以注意到一點,就是在golang當中if後面的條件不加括號,這點和Python一樣。但是如果你寫慣了java或者是C++剛開始可能會不太適應。
最後一點是golang的程式碼規範檢測工具golint當中規定了所有的函式以及結構體頭部必須要寫註釋,並且對註釋的規範也進行了限制。註釋的規範是名稱加上說明,如果不寫或者是不規範的話,程式碼雖然可以執行,但是無法通過golint的規範檢測。一般來說公司的開發環境都會做限制,只有通過golint規範檢測的程式碼才可以提交發布。
另外一點是golang不支援隱式型別轉換,比如int和int32以及int64,會被視作是不同的型別。如果我們將一個int32的變數賦值給int型別,則會引起報錯,必須要我們手動轉換。這當然增加了編碼時候的工作,但是也避免了很多由精度不一樣產生的問題。
除了這些之外,golang當中還定義了對結構體定義以及錯誤處理等內容的規範。但是對於我們初學者而言,目前這些是必須要了解的,其他的內容可以等我們後續遇見了再熟悉。
一門語言對於程式碼風格做了嚴格的規範限制對於初學者而言可能是一件比較蛋疼的事情,因為要記的東西變多了,我們不僅要學會語法,還要搞清楚這些規範。但是當我們熟悉了或者是工作了之後,會發現這其實是一件好事。對於多人協作的場景而言,大家都遵守一樣的規範會大大提升程式碼交流以及協作的效率。如果你們看過其他程式碼風格和自己完全不同的人的程式碼之後,相信你們對於這點一定會有更深的認識。
總結從規範的嚴格程度以及對面向物件的閹割程度看起來,golang簡直不像是一門新生的語言,倒有些上世紀老派語言的風格。但是偏偏golang又有很多新鮮特性,比如允許函式值返回多個結果,支援匿名函式以及部分函數語言程式設計的功能等等。在初學的階段,我也非常抗拒它,可能是因為Python寫得太多了,習慣了動態語言。但是隨著對這門語言了解的深入,我越來越多地發現了它這些設計理念背後的思考和智慧,慢慢對它改觀,時至今日,我已經不再懷疑這是一門優秀的語言,這幾年的流行並不是沒有道理的。
另外很重要的一點是,因為golang太特立獨行了,所以經常會讓我思考它這麼做背後的用意是什麼?這麼一思考,加上查閱一些資料,能夠發現很多之前思維當中的盲點。在之前學習語言的時候,我是絕對不會去思考語言的設計者為什麼要這麼設計的,只會依葫蘆畫瓢,照著把相關的內容學會僅此而已。這樣的思考除了能夠提升對於語言本身的理解之外,也能夠提升對問題場景的思考和理解,對於工程師而言,後者其實是更為重要的。
當然這些內容我光說是沒有用的,也需要螢幕前的你用心去體會。
希望大家都能感受到golang的魅力,都能在此過程當中收穫成長,加油!如果覺得有所收穫,請順手點個在看或者轉發吧,你們的舉手之勞對我來說很重要。