我是如何從 php 轉型寫 go 的

Remember發表於2021-02-06

圖片拍攝於2017年10月3日,麗水冒險島。

本來想延續上一個公眾號 <<不定期更新的日常>>系列,但是想想還是先寫下這篇吧。希望對那些剛轉型 Go 或者有意向轉型的小夥伴有所幫助。

起點

去年七月初的時候,在上家公司感覺到畢業以來第一次瓶頸,加上小公司專案半涼的狀態,隨即提出離職。在交接的過程中,我開始投遞簡歷出來面試,因為學歷並不是很好,加之在開源世界並沒有什麼拿得出手的專案,也就沒對大廠抱有希望,整個期間就面了三家公司,拿了其中兩家 offer,一家做直播的,一家做電商行業的,選擇了電商的那家,不算很大,一千多人還是有的,然後就完成了離職到就職的無縫連線,現在入職半年多了。

面試的時候面的就是 php 崗位,因為也沒別的語言經驗,入職第一週沒有具體的工作安排,就是熟悉環境。第二週開始接了點小需求,評審之後看了下也不是很難。不過新公司第一次上線多少還是有點忐忑的,好在沒出啥問題,一切正常。

來到八月份,因為我們做的是一個全新的專案,我開始搭建一些基礎的,和業務沒什麼牽扯的模組,還對接了一些平臺。

大概到九月初的時候,由於某種場景不太適合使用 php,加上我們有意識的想把純業務的和底層通用模組做分離。瞭解到其他部門在搭建他們的中臺業務也是把技術棧從 php 遷移到 Go,加上內部也有專門的部門去搭建 Go 框架、封裝公用提高業務開發效率的包……,然後老大就過來問我,有沒有意向搞 Go,我的回答是求之不得!!!

我大概花了一天的時候,過一下語法。我之前提到過,看了學院君的 Go 入門教程。簡單的把上面的基礎語法過了一遍,全程敲下來。因為之前有偷偷學過一點,所以沒花多少時間就恢復了之前為數不多的功力。這時候已經能看懂這樣簡單的程式碼了。

package main

import "fmt"

func main() {
  go func() {
    fmt.Println("列印不?")
  }()
}

如果你一直沉寂在 php-fpm 那一套,導致的現象可能是你不知道上面的執行結果。別不信,好多人真的不知道為什麼,當然我沒有黑語言的意思。

接著因為公司內部的框架有基於 gin。我就把 gin 官網的 demo 自己全敲了一遍,我也建議你這樣幹。初學者,要學會從模仿做起,模仿當然就是動手操作。

然後老大就讓一個大佬給我開了一個基於公司內部框架構建的一個業務專案,不是很大,我跑下來之後,根據 readMe 進行系列操作,執行過程也有點坎坷,還踩到一個坑,虛心請教了大佬後才解決。根據這個專案去了解它的執行流程、生命週期以及涉及到的知識點……,這時候千萬不要陷入程式碼細節,細節是魔鬼!

大概過了三天,我就開始動手寫我們部門的專案了,一直寫到現在。這個過程很有趣,我經常在後一天發現前幾天實現的並不好, 然後就是持續重構,持續調整。

我是咋麼發現的呢?

當然是學習!首先,那段時間除了在公司實現需求過程中,遇到 Go 相關不明白的點,比如包之類的,那就去官網搜,或者看一些文章。遇到內部框架不明白的地方,就去請教大佬,大佬對我總是那麼和藹可親。

下班後,我也沒閒著,瘋狂的補充 Go 相關的知識,記得我有次看 sync.Mutex 裡面定義的常量不明白,後面就專門去查了資料。其實是很基礎的東西,程式碼如下,

const (
    mutexLocked = 1 << iota // mutex is locked
    mutexWoken
    mutexStarving
    mutexWaiterShift = iota

)

func main() {
    fmt.Println("mutexLocked的值",mutexLocked)
    fmt.Println("mutexWoken的值",mutexWoken)
    fmt.Println("mutexStarving的值",mutexStarving)
    fmt.Println("mutexWaiterShift的值",mutexWaiterShift)
   //為什麼結果是:
// mutexLocked的值 1
// mutexWoken的值 2
// mutexStarving的值 4
// mutexWaiterShift的值 3
}

想想那時候就有趣。

書籍

當然也要看書,我是在去年12月初知道的,公眾號 polarisux 回覆 ebook,Go 從入門到進階的書都有。

圖片

首先,書並不是越多越好,等你看完相關的書你會發現很多書的知識點同質化。

這時候你要做的是什麼?

除了吸收基礎的知識之外,我還會做一個有趣的事情,就是看兩本書對於相同的知識點的不同闡述,然後你就會發現 A 書未提及的 B 書做了補充,B 書遺漏的點 A 書補上了,

有趣吧?當然了,如果你能延伸出它們都未曾提及的,那麼,請收下我的膝蓋。

我看書有個習慣,並不會從頭看到尾。我認為,一本書並不是每一章都對我有價值,因人而異。

我會選擇性地進行閱讀,對我目前有幫助的或者我需要去掌握落地到具體工作中的,重點去細讀,精讀。並且動手去實踐以及輸出自己的思考。

在讀一本書的時候,一定是帶有目的性的,讀完要得到什麼?是否可以施展到工作?看完了,我能掌握它的用法嗎?最好畫一個類似思維導圖,等讀完書後,回過頭看思維導圖,這些知識點都掌握了嗎?

原始碼

然後就是看原始碼。

當我們不知道怎麼去寫好的程式碼,就需要去學習優秀的人是如何設計程式碼的,可以想象同一個場景,你會如何設計程式碼?再看看別人是如何設計的,對比下,差距大嗎?

我比較喜歡看別人的程式碼,可惜目前看的還不夠多。但是有過從頭到尾把一個小而精專案的原始碼看完,有些知識不一定當場就能吸收,需要慢慢去消化。

看原始碼最避諱的就是一上來就陷入程式碼細節,切記!

對我來說,當我去看原始碼的時候,不管是 Go 本身的,還是第三方包,首先我肯定是已經在使用了,已經知道它的用途,應用場景以及一些使用上的操作,這是前提。

然後需要知道它的整體架構,這個一般專案都會有一個大概介紹,它的模組組成,他們之間的關係、互動,大概就這些,然後分模組去閱讀原始碼,這個過程中,你就能慢慢去閱讀作者的設計,你就能瞭解到作者更多的細節,再聯想到自己,都寫的啥?

總結

這篇文章大體介紹了一下我四個多月的 Go 之路,希望對你有所幫助。另外,我想說的是,學習並不是短跑,它並不會短時間內快速到達終點,更確切的說,它沒有終點。

學習是需要通過持續不斷的積累,才會引發質變。學習方式也並沒有固定的模板,你需要找到一種最適合自己的方式,然後把頭埋下來,堅持。在你累的時候,不要忘記抬起頭,看看前面的路。共勉!

本作品採用《CC 協議》,轉載必須註明作者和本文連結
吳親庫裡

相關文章