( )是網(wǎng)站可以提供給用戶的價值搜狗關鍵詞排名查詢
背景
一直有在零散的時間用go寫點代碼,正好借著最近比較有時間寫東西的契機,給這個看著年輕,實際也已經(jīng)發(fā)展10幾年,并在當下眾多開發(fā)領域都有不可忽視作用的語言做個介紹吧
golang 的起點
golang 的誕生可以說是時代造就了它,它也成就了研發(fā)工具、云原生和高性能服務開發(fā)百花齊放的時代
本節(jié)主要參考文章:
Go at Google: Language Design in the Service of Software Engineering
翻譯-Google 里的 Go 語言:服務于軟件工程的語言設計
煎魚-為什么要開發(fā) Go 這門新語言?
開發(fā)痛點
- 當時谷歌使用的語言:C++、Java 和 Python ,已經(jīng)不適用于計算層面的需求,對于多核處理、大規(guī)模計算 和 web應用編程層面,遇到的問題都只能繞過,而不是直接解決
ced by multicore processors, networked systems, massive computation clusters, and the web programming model
-
軟件規(guī)模:千萬行代碼,數(shù)千程序員共同維護(言外之意就是效率太低了,語言和開發(fā)者兩個層面)
-
編譯時間太長,幾分鐘到幾小時都有(特別講了 C++ #include 在編譯上的消耗: Dependencies in C and C++)
-
依賴混亂,跨語言構建麻煩
-
難以編寫自動化工具
譯者注: 結合原文之后的內(nèi)容來看,最主要的兩類問題就是 大規(guī)模的 C++ 項目編譯時間長,以及多種語言維護成本高的問題
發(fā)明者
Robert Griesemer: 參與過谷歌 V8 引擎的開發(fā),Sawzall 語言(谷歌內(nèi)部用的日志分級打印庫,之后被 go 的日志庫替代)、JVM 和 strongtalk 系統(tǒng)(用于類型檢查,現(xiàn)在不維護了)
Rob Pike:Unix 開發(fā)者之一,為 Unix 編寫過終端,后續(xù)編寫過 sam、acme 文本編輯器,再之后和 Ken Thompson 一起創(chuàng)造了 UTF-8
Ken Thompson: Unix 開發(fā)者之一,B語言(C語言的前身)的發(fā)明者,后面 Dennis Ritchie 基于 B 語言又開發(fā)了 C語言。1983 年 Ken 和 Dennis 一同獲得了圖靈獎
擴展: Russ Cox,你可以在 golang 的很多 issue 中看到他的身影,他也是go代碼提交次數(shù)最多的
推薦閱讀: 圖靈獎歷屆得主、golang talk
吉祥物
名字: Gopher(囊地鼠)
由 Rob Pike 的妻子 Renee French 創(chuàng)作,官網(wǎng)甚至還有細節(jié)描述呢
go 是什么樣的語言
為了解決前面說的問題,go 必須有下面的特點:
- 高效率、可擴展、滿足生產(chǎn)力需求
- 必須有可擴展性,對于代碼量多、依賴多、開發(fā)者多的大型項目 必須能很好運作
- 自帶 GC,并在對象內(nèi)存申請、釋放空間上進行優(yōu)化,保證GC盡量不影響業(yè)務運行
- 符合C的編程習慣,讓程序員能絲滑切換(如: 靜態(tài)類型對象)
- 必須足夠現(xiàn)代化,在多核處理、網(wǎng)絡、web 應用開發(fā)上需要更加方便,也要支持更多新特性,如內(nèi)置的并發(fā)編程方案
時間和版本
golang 版本來源: 從 1.10 到最新
go 語言特點
go 語言特點
本節(jié)中,筆者將結合自己平時開發(fā)過程中使用到的 go 比較核心的特性進行基本介紹,這些也是 go 和其他編程語言最不同的地方,包括 基本語法、基本指令、函數(shù)、關鍵字、基本類型、打包方式等
語法
- 通過大括號劃分代碼塊,保證大項目下依舊結構清晰
- 不需要分號,雖然加了也不會報錯
- 不需要小括號,比如在 if a < b 判斷語句、for 循環(huán)中的判斷,都不需要
- 未使用的 import / 局部變量將報錯,保證編譯不會引入多余的代碼,提升編譯效率
執(zhí)行
- go build: 統(tǒng)一的打包語句
- 編譯后生成一個可執(zhí)行文件
debug
- pprof: 自帶性能指標庫,可通過火焰圖、命令行查看堆棧情況、堆大小、各協(xié)程調(diào)用耗時等
函數(shù)
- 接口不需要顯式說明繼承,只要實現(xiàn)了接口的方法即算是繼承
- 接口可以通過 指針接收器(pointer receiver) 或 **值接收器(value receiver)**實現(xiàn),分別適合 setter 和 getter 的實現(xiàn),大對象的方法也適合用 指針接收器 避免頻繁拷貝(參考: 什么時候適合用什么接收器?)
- 方法可以作為對象傳遞,可以作為 map 的 value、聲明匿名方法、定義閉包(閉包常用于定義配置方法,如 trpc 的 server.Opts 及其具體實現(xiàn)方法)
- 不支持重載,用開發(fā)必須增加少量代碼的代價換來了 代碼可讀性和編譯性能(一些討論)
- 建議使用組合(composition),而不是繼承(inheritance)(對比: java 類在多次繼承后,要找到只在基類實現(xiàn)的方法的源代碼,需要跳很多次才能找到,相反,組合的結構就很清晰,只有一層)
錯誤處理
- 沒有異常機制,通過 error + 函數(shù)返回值 直接返回報錯,在外部及時處理錯誤(也促使開發(fā)者封裝好會出現(xiàn) error 的代碼塊,減少主函數(shù)的層級)
- 通過 panic + recover 機制捕獲協(xié)程中發(fā)生的嚴重錯誤(如空指針)
基本類型和關鍵字
- 切片(slice)和數(shù)組(array): 切片包含數(shù)組、長度(len)和容量(cap)
- map: 非協(xié)程安全的 map(slice 也是非協(xié)程安全的,go 設計上就是讓 channel 成為唯一的協(xié)程間通信對象)
- defer: 常用于釋放資源、panic 處理
- make: 申請切片、map 和 channel 的空間
- init 方法: 被引用的時候,包內(nèi)的所有 init 方法會自動執(zhí)行。單個包內(nèi)的 init 方法執(zhí)行順序按 文件名字段序 -> 方法從上到下 的順序執(zhí)行,參考
- 聲明對象的方式: 通過 var 指定對象名稱和類型,或直接 a := 1,編譯器自動識別字段類型
- const: 聲明常量
- iota: 枚舉,只能是數(shù)值
- 空白標識符: 下劃線(_),可用于忽略返回值,迭代 slice 或者 map 時忽略 下標/key,以及 init import(只執(zhí)行包的 init 方法,不需要顯式調(diào)用包的資源,如: import _ “net/http/pprof”)
- select case: 多個 Channel 同時讀取方式
- 總共只有[25個關鍵字](https://articles.wesionary.team/know-about-25-keywords-in-go-eca109855d4d),相比: C99 有 37 個,C++11 有 84 個
原生庫和方法
- time: 時間,方法有 time.Parse, time.Now, time.DateTime(常量 2006-01-02 15:04:05)等
- io.ReadAll: 數(shù)據(jù)流
- bytes.Buffer: 字符串緩沖
- strings、maps、slices: 集合類型的工具方法,如 strings.ReplaceAll、maps.Clone、slices.Sort 等
- regexp: 正則
- net/http: http 核心庫
- sort: 1.19 之前的數(shù)組排序庫
- log/slog: 1.21 新增的日志庫,支持等級和格式化打印
- sync: 協(xié)程之間同步、狀態(tài)共享的相關組件庫。Mutex: 鎖;Once: 只執(zhí)行一次;WaitGroup: 等待n個協(xié)程執(zhí)行;Pool: 協(xié)程間復用對象;Cond: 等待和喚醒
反射
- reflect.TypeOf: 獲取對象的具體類型
- reflect.Kind: 獲取對象的類別(和類型的區(qū)別: 具體值或指針的類別為 interface / pointer,類型可以拿到具體的 struct或接口類型)
- reflect.ValueOf: 獲取對象的具體值
- struct tag: 標注 struct 內(nèi)屬性的附加信息,一般用于 json序列化、yaml 內(nèi)容解析、orm 字段映射等場景
并發(fā)
- 協(xié)程(Routine): 用戶層的“線程”,通過 go func() 開啟并發(fā)
- 管道(Channel): 協(xié)程間的通信方式
- 上下文(Context): 協(xié)程間傳遞數(shù)據(jù)、父協(xié)程控制子協(xié)程狀態(tài)的媒介
運行時(Runtime)
- GPM: Go 進程的核心,協(xié)程(Goroutine)、處理器(Processor)、系統(tǒng)線程(Machine)
- GC: 三色標記法、混合寫屏障等
包管理
- 從 git 路徑引用依賴,沒有“官方倉庫”的說法,去中心化的設計
- 以 git tag 或者 commit id 作為版本標識
- 對象和方法是否對外可見,通過首字母大小寫來標識,大寫為開放,簡單明了
工具
- gofmt、goformat、staticcheck: 代碼格式化
- test、bench、fuzz: 普通測試、并發(fā)測試、混沌測試
- doc: 文檔,go 的文檔可在源碼中通過注釋編寫,并自動生成
以上就是自己常接觸的原生庫了,可以從 go源碼的src目錄 更多的實現(xiàn)細節(jié)
自己寫的和go有關的博客
golang 編程規(guī)范查漏補缺
golang-使用 go test 輸出單元測試覆蓋率
golang-單元測試和mock框架的介紹和推薦
golang-使用 godoc 工具編寫代碼注釋
golang-文章翻譯-go高效編程
golang-文章翻譯-go常見的10種錯誤
vscode 使用技巧(vscode+go插件的開發(fā)環(huán)境)
go 學習方法總結
官網(wǎng)
Go 的官網(wǎng)其實是最好的學習資料,教程、博客、社區(qū)動態(tài)都有,絕對適合作為入門資料的第一位
下面說明官網(wǎng)中右上角各個欄目的內(nèi)容
為什么使用 Go(Why Go)
大體就是 Go 在一些通用領域的使用場景,以及在大廠的使用情況
Case Studies: 大廠的使用場景,如 Google、CloudFare、Meta、Netflix 等
Use Cases: 在云服務、網(wǎng)絡通信、命令行工具、網(wǎng)頁/客戶端應用 和 運維和可持續(xù)開發(fā)(DevOps、SRE)領域的應用
每一個領域下都有比較流行的開源項目的推薦
Security: 如何提升自己工程的安全性,如通過 govulncheck 檢查項目存在哪些已知漏洞
Learn
非常適合上手的 go tour,幾乎覆蓋了 go,可以說練習完所有示例就會寫 go 代碼了
Docs
所有官方文章: 可以挑講原理的文章看,如 Using and understanding Go 中的 A Guide to the Go Garbage Collector 以及 References 中的 The Go Memory Model
Effective Go: 上手之后,進一步了解 go 編程風格的必讀文章
std: 標準庫文檔
faq: 囊括了從其他語言遷到 go 語言的常見問題,也體現(xiàn)了 go 的設計思想
社區(qū)
blog: go 博客,社區(qū)新動態(tài)
開源項目和代碼推薦
go
go 本身的源碼就很好閱讀,也和 go 本身語法比較簡潔有關。如果你想了解 go 的基礎庫的原理,大可不用搜一堆博客,一點點地消化別人的總結,讀go源碼就是最好的學習go原理的方法
包括: sync, runtime, context, reflect,這些都是 go 的核心庫
web 應用
開發(fā)后臺必須要掌握的就是 web 框架,當然不同公司對它的定制化也會不同,如果想從簡單的入手,使用官方推薦的 gin 就行。想?yún)⒖即髲S實際用的,可參考國內(nèi)開發(fā)者開源的 web 框架(功能比較全),如字節(jié)的 hertz、go-zero、goframe 等
中間件
gorm: 數(shù)據(jù)庫 orm 庫
redis: redigo
kafka: sarama
云原生和監(jiān)控
如 Kubernetes、Istio、Prometheus、Grafana 等,也能接觸到當下比較流行的項目
命令行工具
以往我們需要用工具進行文檔格式轉換、爬蟲、文件批量下載等場景,可能會主要以 python 項目作參考,因為它語法簡單,執(zhí)行方便,你需要的只是一個 python 環(huán)境
現(xiàn)在,擁有類似特性的 go 讓我們多了一個選項,同樣的需求,也可以看 go 社區(qū)有沒有現(xiàn)成的方案。甚至 go 只需要編譯好的可執(zhí)行文件,更加方便
具體用哪個工具因需求而異,可以參考別人的整理,這里列幾個可能比較常用的:
hugo: 博客網(wǎng)站生成,類似 hexo
buffalo: 快速生成 web 項目
vhs: 終端錄制
pget: 并發(fā)下載
fsnotify: 系統(tǒng)文件監(jiān)聽
lux: 網(wǎng)站視頻下載工具(不能下載需要登錄才能下的超高畫質(zhì))
migrate: 跨不同類型數(shù)據(jù)庫遷移
博客推薦
golang 在國內(nèi)大廠實踐還是比較多的,因此國內(nèi)開發(fā)者寫的博客也不會缺少。本著技術的學習方法來說,這里推薦兩個博主 分別對應前沿動態(tài),和深度剖析原理
煎魚: go 語言開發(fā)者,對 go 社區(qū)動態(tài)、新版本特性的跟蹤比較及時,類似的博主還有 polarisxu
go語言設計與實現(xiàn): go 原理和設計思想,這個博客對技術的思考方式值得應用到所有技術的學習上: 從為什么這么設計的問題基礎上,去理解技術實現(xiàn)細節(jié)