如何快速高效率地學習Go語言
阿新 • • 發佈:2020-03-18
要想快速高效率地掌握Go語言,關鍵是要通過不斷寫程式碼去訓練,熟能生巧。方法是沒問題的,但具體的路徑呢?就像開車,能不能給個導航?我希望這篇文章能起到一個導航的作用,這裡提供的路徑,應該對很多人都適合。當然每個人的具體情況不同,因此路徑會有差異。你可以對這個路徑進行剪裁,得到最適合自己的。
#### 目標(快速,高效率):
短時間和高效率是這裡的關鍵詞。其實只要你每天用Go來編寫程式,時間一長,也就掌握了,它不需要任何技巧,大智若愚,實際上是一個不錯的辦法。但如果你想最快地掌握Go語言,還是需要一些技巧的。
我以前也曾經學過一段Go,大概花了2周,基本的會了,但遠遠沒有達到掌握的程度。後來因為有其他事情就放下了。現在回想起來,當時方法不對,效果也不好。後來用我現在要講的方法,在不到2個月的時間完全掌握了Go語言。這也得益於我以前對Java比較熟。
#### 最終結果(掌握Go語言):
什麼叫完全掌握Go語言?下面是我的標準:
1. 對語言本身已掌握,可以直接在鍵盤上敲程式
2. 給你一個專案,你大致有思路應該怎麼做,知道要從那下手而且能比較順暢地做出來。
其中#2又包括兩點:
2.1. 熟悉常用的架構
2.2. 知道如何用Go語言來實現常用架構中的各個環節
其中#2.1是跟語言無關的,需要長時間的程式設計積累,不是短時間能完成的。#2.2是跟Go語言直接相關的,在瞭解語言的標準庫的基礎上還要熟悉常用的框架和第三方庫。好訊息是Go的標準庫非常強大,你的主要精力要放在標準庫,除此之外你只需要兩三個外來庫就行了。
#### 適用人群:
這個方法只適用於已有其他語言程式設計經驗的人,這樣可以藉助已有的其他語言經驗,達到快速掌握Go的目的。其中2.1跟Go語言無關,主要是你以前的程式設計積累。你要做的是完成#1和#2.2。
高效率學習的關鍵是要進入一種正向反饋的自迴圈系統。在你掌握了基本Go語法之後,通過不斷用Go寫程式碼來加深對語言的瞭解和熟悉程度,之後就可以寫更多、更深、更好的程式碼,這樣就形成了正向反饋的自迴圈系統。像滾雪球一樣,越來越大。
快速的關鍵是用最短的時間進入這種自迴圈,也就是儘快瞭解Go基本語法。
#### 學習路徑和導航:
學習分四個階段。 完成之後,你應該已完全掌握Go語言。
1. 瞭解基本語法 (時間2天-7天)
2. 深入掌握Go知識點 (時間2周-5周)
3. 自己動手完成一個有一定規模的專案 (時間1個月-3個月)
4. 掌握Go的其他庫,如“Goroutines”,“context”,“net/http”
當你完成1-3之後,你已基本掌握Go語言。#4幫你完成對整個語言的完整掌握。
以上4條給你提供了一個大致的導航,這樣你就知道了要去哪,中間路徑怎麼走,現在到哪了,還需要多長時間才能到達。
上面的時間只是個略估,每個人的程式設計背景不同,每天所花的學習時間不同,最終完成時間和效果也會有不少差異。
#### 學習內容:
##### 瞭解基本語法(第一階段):
這一階段的目的是快速瞭解Go語言的基本語法(不必深入領悟細節),能自己編寫簡單程式(它包括安裝Go),找到一個合用的IDE。最好的的教材是“Go by Example 中文”。你不必完成所有的專案,只完成前面20個就行了。很多人推薦[“Go 語言之旅”](https://tour.go-zh.org/welcome/1) 這**不是**個好主意。 它對一些知識點摳的太細,不利於快速進入正向自迴圈。[“Go by Example”](https://books.studygolang.com/gobyexample)講得很淺,即使你學會了實際上也並沒有深入掌握知識點( 那是第二階段的任務),但第一階段只要知道大概就行了。正因為這樣“Go by Example”才是最好的選擇。
##### 深入掌握Go知識點(第二階段):
第二階段的任務是掌握Go的主要知識點,大概有二三十個。 例如arrays和slices的區別,函式呼叫時傳參還是傳值(如果傳值怎樣改變引數的值?),指標的用法,Go中哪些型別是指標型別(Interface是指標型別嗎?),Errors,Methods,package,go-sql,date 和time等等。這些看著簡單,但實際上要真正掌握還是要費一些時間的。
在這一階段,你可以通過寫一些小的程式來掌握知識點。比如寫一個訪問資料庫的程式,有增刪改查功能,資料庫欄位包括各種型別(時間型別會複雜一點)。然後在這個基礎上增加域模型,把程式分層。
關鍵的一點是不要拷貝別人的程式,一定要自己用鍵盤把程式敲出來(能敲出一個字算一個,只有實在想不出來了再去看“Go by Example”)。只有這樣才能真正學到。剛開始可能會比較痛苦,但只有痛苦了,你才能學到東西,而且這是最快的方法。(當然,當你掌握了Go語言之後再拷貝別人的程式就沒有問題)
比較好的狀態是你每天都有問題,不斷地向自己提問(然後去解決問題),問題解決了,知識點就掌握了。提不出問題怎麼辦?不拷貝別人的程式是一個好辦法,我發現當自己用手一個字一個字地敲程式時(而不是拷貝別人的程式時)會不自覺地思考很多問題並注意到了很多以前忽略了的地方。比如說,像上面“函式呼叫時傳參還是傳值?”,你能不能自己寫個程式測試一下,這樣自己就能把問題回答了,而不必到網上查資料去找現成的答案。測試時,如果型別是“string”或“int“很容易,如果是map, struct呢?測試之後可能還有問題,這樣再去看文章就有針對性,效果會更好。這種情況下,學習過程是完全有你來主導,是效率最高的。但需要你有比較好的程式設計基礎。
如果你每天提的問題不多,還不足以主導整個學習過程,那你需要看書或看網上的文章來輔助。但需要注意,它只是起輔助作用,重點還是要通過寫程式碼來領悟。每次看書的時間不要太長,太長了容易被它的思路帶著走,限制了自己思維的活躍性。每次看文章只針對一個問題,充分聚焦。如果不是帶著問題而只是泛泛地看書很可能當時看明白了,但第二天就又糊塗了或忘了。只有自己想明白的道理才是你自己的,書上的都是別人的知識。這樣每天大概掌握1-3個知識點,天天都能感覺自己在進步,這就是最好的一種學習狀態。
##### 另外有三個技能也很重要:
1. 快速查錯和除錯的能力
Go的錯誤資訊還是比較清楚的,你應該可以很快發現問題在哪。關鍵是要找到出錯的檔案和行數。程式碼中清晰的日誌輸出和程式錯誤資訊能幫你快速定位。如果你想要知道怎樣列印程式錯誤的”stack trace“ , 那就看一下這個[“Stack Traces and the Errors Package”](https://dave.cheney.net/2016/06/12/stack-traces-and-the-errors-package). 如果是程式結構有問題,那麼Go不會給出錯誤的檔名和行數, 這時就困難一點,要看你對Go執行環境的理解。
2. 快速得到函式或struct的文件
好的IDE非常重要,最重要的功能是檢視函式或struct的文件和跳轉到某個函式。 “GoLand”是最好的IDE,但檢視函式文件的和跳轉的功能不好用(組合鍵過於複雜),不過你自己可以重新設定組合鍵(我設定的是點選滑鼠的滑輪,因為別的方便的鍵都被用掉了)。“Visual Studio Code”把滑鼠移過就能看函式文件,非常方便。但在我的機器上反應太慢了,只好棄用。
3. 檢視第三方庫的原始碼
Go的超絕優勢是當它載入第三方庫時,載入的是原始碼而不是可執行程式。這大大加快了它的學習進度。我在學習日誌庫Zap時,由於它的配置引數多達十幾個,我怎麼也找不到完整的例項說明,試了很多組合都失敗了。後來看了原始碼,很快就解決了問題。從這之後,碰到解決不了的第三方庫的問題,我就經常會看原始碼,大多數時候都能把問題解決。由於在Go裡看別人的原始碼太容易了,有時候我都沒有意識到看的是別人的原始碼。後來再用別的語言程式設計時,不能很方便地檢視第三方庫的原始碼,覺得非常不方便,就想到了還是Go好。
##### 完成專案(第三階段):
這時你已掌握了Go語言的基本知識點,是時侯寫一個真正的可以在生產環境執行的程式了。
我建議你選一個熟悉的領域,比如一個簡單的電商或學生註冊課程的程式。大概有兩三個域模型類(struct)和資料庫表。程式可以分成三層,域模型層,業務邏輯層和持久層。先不需要有使用者介面。各層之間要通過介面呼叫, 這樣你可能還要通過容器(Application Container) 產生具體型別(Concrete Type)並用依賴注入(Dependency Injection)注入到函式中。這樣就有一定的複雜度了。當然這裡面牽扯到不少的設計問題。 如果你暫時不想考慮太多設計問題,那你只要把程式做出來就行了,也能達到掌握Go語言的目的,不過掌握的級別不一樣。 你也能寫出熟練的Go程式,只是不知道如何設計而已。
如果你想把設計也包括進去, 那你要思考很多問題,例如程式的目錄和包結構,設計架構和分層,編碼規範,日誌和錯誤處理,是否要支援事務。我在GitHub上完成了一個完整的程式,並且寫了一些列的文章[“清晰架構(Clean Architecture)的Go微服務”](https://blog.csdn.net/weixin_38748858/article/details/104353016)講述上面的每一方面。 不過我不建議你一開始就看它。你需要自己先反覆考慮這些問題,仔細設計。不需要一步到位,可以不斷地對設計和程式進行重構。這中間你可能會碰到各種各樣的問題,你需要在不斷解決問題中成長。當你寫到一定程度時,你可以去看上面提到的文章,跟你的設計和想法進行對比,印證。 如果有興趣我們還可以討論,共同提高。
##### 掌握Go其他庫(第四階段):
這時你已經基本掌握了Go, 再學習其他的庫就會很容易,例如“Goroutines”,context”,“net/http”。我之所以把這些放在第四階段是因為它們不影響核心功能又有一定難度,放在最後,學習坡度會比較平緩。
#### 學習內容的選擇:
如果你只想掌握Go語言,對時間沒有要求,那麼內容的選擇並不重要,任何學習內容和學習順序都是有幫助的。如果你希望在最短的時間內學會,那麼內容的選擇和學習的先後次序就比較重要了。下面是我的一些建議,當然你可以根據自身情況量體裁衣。
##### 知識點選擇:
主要針對學習的第二階段。不建議上來就直接使用第三方庫。Go語言本身標準庫非常強大,能做很多事情。使用第三方庫反而會妨礙你對Go語言本身的理解。開始的時候還是聚焦於語言本身。下面是部分可選知識點:
Module
strconv
string
time
go-sql
logging
。。。
##### 專案選擇:
主要針對學習的第三階段。我不主張一開始就選擇一個gRPC或Web的專案,因為它需要你額外瞭解gRPC或Web,這樣會分散你的注意力,你需要同時學習Go和gRPC或Web, 會加大難度。當然如果你已經對他們很熟悉就另當別論。原則是你一定要選擇一個阻力最小的方向,也就是你最熟悉的專案。對多數人來講,一個簡單的訪問資料庫的程式應該是阻力最小的。完成這個之後,如果你願意,可以在它的基礎上加上gRPC或Web功能,如果你的架構合理,加上gRPC或Web會是一件很容易的事。
##### 拓展庫選擇:
主要針對學習的第四階段。有些人對Go“Goroutines”有誤解,覺得它很容易。如果只是簡單地寫一個“Goroutines”確實容易,但實用的“Goroutines”都需要“Goroutines”之間通訊和進行協調控制,要寫出能在生產環境中可靠執行的“Goroutines”並不容易。有人專門做過調查,Go的“Goroutines”雖然比Java的“thread”要容易得多,但在程式中產生問題的概率一點也不比Java低。如果是團隊專案的話,最好是在設計時就把“Goroutines”程式碼和其他程式碼分開,並由專人負責。下面是一些可以在第四階段學習的庫:
Goroutines (Channel)
net/http,
net/url
O/R mapping
reflect
##### 文章選擇:
決定那些文章要讀,那些可以不讀,這裡主要針對Go官網上推薦的文章,在下載Go時就自帶的。
**需要讀**:
How to write Go code:
effective go:還是有幫助的,但文章太長又枯燥,建議每天只讀一段,花兩週時間讀完,這樣不會太累。
**不需要讀**:
go faq:
關於Go語言歷史和特點:可以掌握Go之後再讀
##### 時間的選擇:
學習的過程同時也是遺忘的過程,只有成長的速度遠遠快於遺忘的速度才能一直進步。最好的方法是集中一段時間主要用來學習Go,假設每週花20小時,一個月基本小成,兩個月就完全掌握了。如果每天花2個小時(一週14個小時),我估計由於遺忘的作用,可能要兩個月小成,四個月才能完全掌握了。如果每天一個小時,我估計一年也學不會。寫到這突然有點洩氣,發現這才是問題的關鍵,感覺前面都有點白寫了。結論是如果是業餘想掌握Go確實需要比較大的毅力。
你可能要問,完全掌握了之後如果一段時間不用,難道不會忘記嗎?也會忘,但那時你對Go語言本身有了深刻的理解,很短的時間就能撿起來。如果只是半生不熟的掌握,過了一段時間不用之後,就所剩不