這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。GERGELY NEMETH 2018-02-08近幾年, Kubernetes 一直是容器編排和管理平台的首選。對於我來說,也很想搞清楚它的底層是如何工作的,所以我決定來學一學 Go 這門語言。在這邊文章中,我會基於我的經驗,並從一個 Node.js 工程師的視角出發。因此我會特別關註:- 依賴管理- 如何處理非同步作業那就讓我們開始吧 :)## 什麼是 Go ?> Go 是一個開源的程式設計語言,它能讓構造簡單、可靠且高效的軟體變得容易. - golang.orgGo 由 Google 的 Robert Griesemer, Rob Pike, 和 Ken Thompson 於 2009 年發布。它是一款靜態類型的編譯語言,擁有垃圾收集機制,基於 CSP 並行存取模型來處理非同步作業。 Go 還有類 C 的文法:```gopackage mainimport "fmt"func main() {fmt.Println("hello world")}```安裝 Go: 官方指導連結: https://golang.org/doc/install.## Go 的依賴管理如果打算寫大量的 JavaScript 代碼,首要問題就是依賴管理問題,Go 是怎麼處理的呢?有兩個辦法:- go get- dep用 npm 的術語來說,你可以把他們看作是:在你需要使用 npm install -g 的時候,使用 go get,然後使用 dep 來管理不同項目的依賴。要安裝 dep,可以通過 go get 來安裝,使用如下命令:```go get -u github.com/golang/dep/cmd/dep```然而,使用 go get 有一個缺點 —— go get 並不處理版本,它僅僅是擷取 Github 倉庫的最新版本。這就是為什麼推薦大家安裝並使用 dep。如果是 Mac 系統,安裝 dep 也可以通過如下命令:```gobrew install depbrew upgrade dep```(如果是其他動作系統,安裝請參見: https://golang.org/doc/install)一旦安裝了 dep,你就可以使用 **dep init** 來初始化項目,就好像使用 **npm init** 初始化 nodejs 項目一樣。> 開發Go項目之前,你需要花點時間設定好GOPATH環境變數。—— [官方指導連結](https://golang.org/doc/install)dep 會像 npm 一樣,建立一個 Node.js 項目中類似 package.json 的檔案來描述工程 —— Gopkg.toml。類似 package-lock.json,也會有一個 Gopkg.lock 檔案。不同於 nodejs 項目將依賴放入 node modules 檔案夾中,dep 將依賴放入一個叫作 vendor 的檔案夾中。要添加依賴,你只需要運行 dep ensure -add github.com/pkg/errors 命令。運行結束後,這個依賴就會出現在 lock 和 toml 檔案中:```[[constraint]] name = "github.com/pkg/errors" version = "0.8.0"```## Go處理非同步作業當用 JavaScript 寫非同步代碼時,我們會用到一些庫或者語言特性,比如:- async 庫- Promises- 或者非同步函數有了它們,我們可以很輕易的從檔案系統中讀取檔案:```javascriptconst fs = require('fs')const async = require('async')const filesToRead = ['file1','file2']async.map(filesToRead, (filePath, callback) => {fs.readFile(filePath, 'utf-8', callback)}, (err, results) => {if (err) {return console.log(err)}console.log(results)})```再讓我們來看看 Go 是怎麼實現的:```gopackage mainimport ("fmt""io/ioutil")func main() {datFile1, errFile1 := ioutil.ReadFile("file1")if errFile1 != nil {panic(errFile1)}datFile2, errFile2 := ioutil.ReadFile("file2")if errFile2 != nil {panic(errFile2)}fmt.Print(string(datFile1), string(datFile2))}```我們來一行行看看上面代碼是怎麼工作的:- *import* —— 有了 import 關鍵字,你可以引入項目依賴的包檔案,就像 Node.js 中的 *require*- func main —— 應用程式的入口- ioutil.ReadFile —— 該函數嘗試去讀取檔案,並由兩個傳回值:- datFile1 如果讀操作成功,- errFile1 如果讀取過程中有錯- 你可以在這裡處理錯誤,或者直接讓程式崩潰- fmt.Print 僅僅是列印結果到標準輸出上面的例子是可以正常啟動並執行,但是讀取檔案是一個接一個讀取。—— 讓我們來稍加改進,將它非同步化吧!Go有一個叫作 *goroutines* 的概念來處理多線程。一個 *goroutine* 是一個輕量級的線程,它由 Go runtime 來管理。*goroutine* 使得你可以並發地跑Go的函數。我最終使用 *errgroup* 包來管理或者說同步 *goroutines*。這個包提供同步機制,錯誤傳播,以及對同一個由一組 *goroutines* 子任務組成的公用任務提供上下文取消機制。有了 *errgroup*,我們可以重寫讀檔案的程式碼片段,並發地執行:```gopackage mainimport ("context""fmt""io/ioutil""os""golang.org/x/sync/errgroup")func readFiles(ctx context.Context, files []string) ([]string, error) {g, ctx := errgroup.WithContext(ctx)results := make([]string, len(files))for i, file := range files {i, file := i, fileg.Go(func() error {data, err := ioutil.ReadFile(file)if err == nil {results[i] = string(data)}return err})}if err := g.Wait(); err != nil {return nil, err}return results, nil}func main() {var files = []string{"file1","file2",}results, err := readFiles(context.Background(), files)if err != nil {fmt.Fprintln(os.Stderr, err)return}for _, result := range results {fmt.Println(result)}}```## 用 Go 來構建一條 REST API在 Node.js 中,當談及到選擇一套架構來寫 HTTP 服務的時候,我們有一堆的選擇。Go 在這方面也不例外。Google 一下後,我選擇 *Gin* 來開始。*Gin* 的介面類似於 *Express* 或者 *Koa*,包含中介軟體支援,JSON 校正以及渲染:```gopackage mainimport "github.com/gin-gonic/gin"func main() {// 建立預設不帶任何中介軟體的路由r := gin.New()// 預設gin的輸出為標準輸出r.Use(gin.Logger())// Recovery中介軟體從異常中恢複,並回複500r.Use(gin.Recovery())r.GET("/ping", func(c *gin.Context) {c.JSON(200, gin.H{"message": "pong",})})// 監聽 0.0.0.0:8080r.Run(":8080")}```這就是我目前掌握的 —— 還沒有生產經驗。如果你這篇部落格對你有協助,並且你想學到更多關於 Go 的東西,就跟我聯絡吧,我會持續分享我的 Go 學習之旅。## 更多資源上面文章主要參考了如下連結文章:- https://peter.bourgon.org/go-best-practices-2016/- https://golang.github.io/dep- https://blog.golang.org/defer-panic-and-recover- https://gobyexample.com- https://www.golang-book.com/
via: https://nemethgergely.com/learning-go-as-a-nodejs-developer/
作者:GERGELY NEMETH 譯者:Chandler1142 校對:rxcai
本文由 GCTT 原創編譯,Go語言中文網 榮譽推出
本文由 GCTT 原創翻譯,Go語言中文網 首發。也想加入譯者行列,為開源做一些自己的貢獻嗎?歡迎加入 GCTT!
翻譯工作和譯文發表僅用於學習和交流目的,翻譯工作遵照 CC-BY-NC-SA 協議規定,如果我們的工作有侵犯到您的權益,請及時聯絡我們。
歡迎遵照 CC-BY-NC-SA 協議規定 轉載,敬請在本文中標註並保留原文/譯文連結和作者/譯者等資訊。
文章僅代表作者的知識和看法,如有不同觀點,請樓下排隊吐槽
811 次點擊 ∙ 1 贊