首頁  >  文章  >  後端開發  >  這就是我在兩週內學到的關於 Go 的全部內容!

這就是我在兩週內學到的關於 Go 的全部內容!

Barbara Streisand
Barbara Streisand原創
2024-10-31 04:27:02690瀏覽

This is all what I

當你需要學習新事物時你的方法是什麼?我有一個非常具體的,我在學習 Golang 時再次測試了它!

要講的內容太多了,但我的目的是列出我發現有用的並且我專門花時間正確學習的內容。

目錄

  • 1.序言
  • 2. 認識 CLI
    • 2.1 CLI:go mod
    • 2.2 CLI:運行
  • 3. 比較不同的語法
    • 3.1 語法:類別/結構體與 API 封裝
    • 3.2 語言:介面實作很奇怪 AS FUC*
  • 4. Stdlib:絕對是個很棒的工具包
    • 4.1 套件:原始型
    • 4.2 包:有用的東西
  • 5. Go 中的測試就是這麼簡單
    • 5.1 檢定:基本檢定
    • 5.2 測試:Jetbrains 樣板
    • 5.3 檢定:執行測試
  • 6.當心循環導入
  • 7.延後這個,延後那個…但是,什麼是延後?
  • 8.菜鳥錯誤管理
  • 9.結論壯舉:低延遲編碼挑戰

1. 序言

在過去的兩周里,我一直在使用 Golang 學習和建立小型應用程式。目前,透過許多直播已經完成了近 50 小時的程式碼,能夠學到一些我之前在語言方面遇到一些小問題的東西真是太棒了。

在這兩週的旅程中,我精心設計了:

  • 一個小而非常簡單的外殼
  • Redis 基本上實作
  • HTTP 1.1 協定實作
  • DNS 伺服器實作
  • 以及一家非常酷的公司的工作測試(將在本文末尾提供)。

這一切都是因為我的老闆再次要求我學習一項新技術來處理一些ScyllaDB PoC 和演示...我對這個決定不太滿意,但是好吧,這是我的工作。

去年我一直在學習 Rust,它對我來說可能仍然太複雜,但我學到了一些非常酷的概念,這些概念讓我轉向 Go 的過程非常順利!

在這篇文章中,我將為您提供一些技巧和建議,以加快您的學習流程。

2. 認識 CLI

我是一名PHP 開發人員,我習慣了有史以來最好的CLI(是的,它是Artisan),但是在我作為開發人員的旅程中,我經歷過一些很棒的項目,其中許多都是......:

  • 貨(生鏽)
  • NPM (JS)
  • 作曲家 (PHP)
  • 等等...

當我進入 Go 環境時,它開始成為一個真正的問題。至少對我來說,Golang 在工具和文件方面的開發體驗還可以好很多。考慮到這一點,我決定從一開始就學習必須學習的 3 個命令。

記住:這只是一個帶有我自己解釋的演練。如果您需要詳細信息,請打開文檔:)
另外:go docs 很糟糕,請有人在那裡放一支語法螢光筆

2.1 CLI:go mod

根據您是否想要模組化應用程式或擁有一個有組織的環境,這將是最有用的命令。

go mod 指令管理專案中的所有依賴項,並負責自動刪除不再使用的任何內容。

首先,在新的空資料夾中,讓我們使用 go mod init 在專案內初始化一個新模組:

mkdir go-fodase
cd go-fodase

# go mod init <module-name>
go mod init github.com/danielhe4rt/go-fodase

這將在專案根目錄中建立一個名為 go.mod 的新文件,它基本上是目前的內容:

  • 模組名稱
  • 您的 Go 版本

這是文件,如果您想自己檢查一下:

# folder: ~/go-fodase
cat go.mod

# module github.com/danielhe4rt/gofodase
# 
# go 1.23.2

之後,我真正喜歡的下一個東西是 go mod tidy,它基本上添加了所有缺失的依賴項並刪除了未使用的依賴項。

go mod tidy

第二個只是為了讓您記住這個存在並且非常有用!也許你的環境每次都會運行它,你會習慣看到導入消失:p

2.2 CLI:運行

這可能是您將使用的最常用命令,因為您必須運行項目,但它的工作原理如下:

  • 您應該指向包含 main() 函數的檔案。
  • 此檔案不必位於資料夾的根目錄中。

關於這個指令最重要的一點是,當你執行 go run 指令時,它會在目前目錄中尋找 go.mod 文件,並將其用作對應整個專案(導入、套件)的基礎。 , ETC)。以下是一些例子:

# go run <your-main-file>

# Environment 1
# .
# ├── go.mod
# └── main.go
go run app.go

# Environment 2
# .
# ├── go.mod
# └── src
#     └── main.go
go run src/app.go

這是我們的 app.go 內容:

package main

import(
    "fmt"
)

func main () {
    fmt.Println("whats up! don't forget to like this article <3")
}

現在您已經了解執行專案的基礎知識了!從字面上看,你好世界!

3. 比較不同的語法:

我對 Go 的問題一直是它的編寫方式,但經過幾個小時的編碼後,我意識到它比我想像的要簡單。正如您可能已經猜到的,我擁有深厚的 PHP 背景和一些 Rust 經驗。

當我在2023 年開始學習Rust 時,幸運的是,我的忠實粉絲Nuno Maduro(Laravel)做了一個名為“PHP for Rust 開發人員”的演講,這給了我一些基本的介紹文法給了我一些喘息的空間,而我完全被Rust踩踏了

總之,當時對我有用,為什麼不做一些比較呢?

3.1 語法:類別/結構體和 API 封裝

在 OOP 中,我們有類,這是一種將程式碼抽象化為小塊的非常酷的方式,並且您擁有「類似的」東西。 Golang 可以被視為一場奧德賽,因為它可以是一個史詩般的開發,可以將環境變成你想要的任何樣子。

請記住,Golang 是一種“高級語言”,它提供“系統級”語法,使您可以輕鬆地使用“低級”實現。

Go文法下,你可以

  • [結構] 透過在類型前面加上前綴、新增「類別/結構」名稱,然後加入結構後綴來定義結構。
  • [封裝] 以 UpperCaseLowerCase 名稱開頭來定義與類別/結構相關的元素的暴露。
    • [Visibility: "public"]:將專案名稱設定為大寫。
    • [Visibility: "private/protected"]:將項目名稱設定為小寫。

您可以將其用於:結構體、結構體欄位、結構體方法。仔細看看:

mkdir go-fodase
cd go-fodase

# go mod init <module-name>
go mod init github.com/danielhe4rt/go-fodase

在 Rust 中,你有一個更明確的方法(更像 oop 的語言),其中:

  • [Struct] 使用前綴 struct 定義一個結構,加入您的「類別/結構」名稱即可。
  • [封裝] 如果你想讓某些東西對其他「板條箱」公開,你應該在你想要公開的程式碼部分加上 pub 前綴。
# folder: ~/go-fodase
cat go.mod

# module github.com/danielhe4rt/gofodase
# 
# go 1.23.2

我想讓 PHP、Java 等內容變得明確,但如果你停下來想想寫的程式碼更少,但這也會影響可讀性。

3.2 語言:介面實作很WEIRD AS FUC*

說實話,我是那種會嘗試將 LARAVEL 放入 Go 環境中的人,我不知道,但這已經在 Goravel 中完成了。不管怎樣,我真的很喜歡使用“介面/契約驅動開發”,的想法,並且這是我第一次在一種語言中陷入困境。

在 Go 中,介面並不是在結構/類別中「實作」,對於像我這樣的 OOP 人員來說,讓這樣的設計決策融入我的頭腦真是太瘋狂了。看看預期的結果:

mkdir go-fodase
cd go-fodase

# go mod init <module-name>
go mod init github.com/danielhe4rt/go-fodase

現在,說到去:你在結構內部沒有「介面」的明確實現,那就是,嗯... 奇怪?相反,您只需實作介面所需的方法,這些方法將在編譯時為您進行檢查。公平地說,這是一種編譯語言,它永遠不會成為問題,但我正在談論我對開發者體驗
的看法

# folder: ~/go-fodase
cat go.mod

# module github.com/danielhe4rt/gofodase
# 
# go 1.23.2

無論如何,只要花一些時間用該語言編碼,您就會習慣它。現在,讓我們來談談基礎環境為您提供什麼而無需下載任何東西!

4. Stdlib:絕對是個很棒的工具包

現在我正在談論Go透過標準庫為您提供的一切,而無需下載第三方包。以下是一些按時間順序排列的時間表:

  • 第一天:什麼?為什麼不像 JS/Java 那樣型別包含所有方法? (我討厭他們兩個)
  • 第一週:等等,也許這很好(在了解了原始類型的包之後)
  • 第二週:什麼?為什麼其他語言預設沒有這麼好的函式庫?

我不是開玩笑,每天我探索 Go 時,我都會在標準庫下發現一些很酷的函式庫。那麼,讓我們開始討論原始類型。

4.1 包:原始型

與PHP 一樣,許多其他語言(Rust、Java、JS 等)不同,Golang 需要「helper」 函數來執行大多數相關的類型操作。我們可以將它們視為「貧血」類型,因為它們沒有附加的「實用性」。

go mod tidy

因此,如果您正在使用 「字串」類型,您可以使用其他軟體包(如 strconv 或 strings)來操作它!但這裡有一條黃金法則,永遠不要忘記要查看哪個套件:如果您的類型是字串,請尋找具有複數名稱的相同套件!

簡而言之,這將為您提供與 []Type 和 Type:

相關的函數
  • 字串類型 -> import ("strings") 用於下列運算:Contains()Upper()Split() ...
  • 位元組類型 -> import ("bytes") 用於Include()Compare()Split() .. .
  • 等操作
  • 等等!

看一下程式碼,方便自己驗證:

# go run <your-main-file>

# Environment 1
# .
# ├── go.mod
# └── main.go
go run app.go

# Environment 2
# .
# ├── go.mod
# └── src
#     └── main.go
go run src/app.go

這應該很簡單,但我掙扎了一段時間,直到進入我的腦海。也許使用 Laravel 及其輔助函數太多年讓我忘記了在沒有框架的情況下編碼是多麼困難 :D

4.2 包:有用的東西

在探索工具和專案時,我對許多專案都有了​​很好的介紹,我想列出每個專案以及我使用過的程式庫:

  • 建立自己的 Shell 挑戰:
    • 套餐:
      • fmt: I/O 庫(掃描/讀取並在螢幕上寫入內容)
      • os: 直接與您的作業系統對話的函數和助理。
      • strconv:將特定資料類型轉換為字串或將字串轉換為任何定義的類型。
  • 建立您自己的 (HTTP|DNS) 伺服器挑戰:
    • 套餐:
      • net: 與網路 I/O 協定(如 HTTP、TCP、UDP 和 Unix Domain Sockets)的整合層
      • [之前的套餐...]
  • 中階家庭作業任務分配?
    • 套餐:
      • flag: 將 CLI 參數捕捉到變數中
      • log: 將 Log 的頻道加入您的應用程式
      • 加密/蘭特:安全加密隨機產生器
      • 數學/蘭特:數學數字隨機產生器
      • 時間:持續時間/時間庫

這是所有套件實現的可捲動視圖,以便您可以查看它們。這裡有很多很酷的 std 包可以引用。

注意:這是很多程式碼! :p
不要忘記評論您最喜歡的功能(除了 goroutine 和通道):p

mkdir go-fodase
cd go-fodase

# go mod init <module-name>
go mod init github.com/danielhe4rt/go-fodase

說真的,這太棒了!那麼,現在讓我們繼續測試吧。

5. Go 中的測試就是這麼簡單

在我使用 Go 的第二個專案中,我看到了在建立 Requests 和 Responses 物件時學習測試的機會。在 PHP 環境中,您可能正在使用第三方函式庫,例如 PHPUnit 或 Pest。正確的?在 Go 環境中,這簡單!您需要做的就是:

  • 在套件內建立一個檔案: 在 person.go 中,您將編寫要測試的函數;
  • 為您的套件建立一個測試檔案:** 建立一個名為 person_test.go 的檔案並開始編寫您自己的測試!

假設我們的套件資料夾中有 requests.go 和 requests_test.go,其中 requests.go 是:

# folder: ~/go-fodase
cat go.mod

# module github.com/danielhe4rt/gofodase
# 
# go 1.23.2

5.1 測試:基本測試

如果 (t *Testing.T).Errorf() 未在測試函數中調用,則 Go 中的測試被視為通過(綠色)。它也遵循前面介紹的相同封裝概念:

  • 測試函數大寫字母開頭由測試運行者識別
  • 測試函數小寫字母開頭的將被忽略(通常是輔助函數)
mkdir go-fodase
cd go-fodase

# go mod init <module-name>
go mod init github.com/danielhe4rt/go-fodase

您可以做自己的輔助函數來測試。只要確保在這些測試中不要侵入模組域即可!

5.2 測試:Jetbrains 樣板

我從第一天就開始使用Goland,所以大多數事情對我來說都比較容易。因此,每次我開始新的測試時,我都會得到這個帶有預設並行運行(goroutines)的 Unity 測試結構的樣板。

# folder: ~/go-fodase
cat go.mod

# module github.com/danielhe4rt/gofodase
# 
# go 1.23.2

5.3 測試:運行測試

好的,現在我們知道在 Go 中編寫測試是多麼容易,但是運行它們怎麼樣? 簡單的任務!您需要做的就是導航到套件資料夾並運行:

go mod tidy

請寫下一些對你的東西的測試。如果你解耦所需的東西,這並不難:p

6.謹防循環導入

在我過去幾年的開發過程中,我一直嘗試以適合我的需求的方式模組化我的所有項目,而不是陷入「乾淨的拱門」或「領域驅動設計」的東西。然而,在我第一次嘗試拆分包時,我收到了「循環導入」錯誤,並心想:我多久沒見過這樣的東西了?

在 PHP 的 2 年裡,我遇到了同樣的導入地獄問題,你無法在特定流程中不導入同一個文件兩次。那是在我遇到 PSR-4(自動加載)之前(它永遠改變了我的 PHP 時代!!),而現在,幾年前,我在 Go 中遇到了這個問題。

讓我們考慮一個循環導入的場景:

# go run <your-main-file>

# Environment 1
# .
# ├── go.mod
# └── main.go
go run app.go

# Environment 2
# .
# ├── go.mod
# └── src
#     └── main.go
go run src/app.go

當您嘗試在 Go 中編譯標記循環導入的內容時,您將收到以下錯誤:

package main

import(
    "fmt"
)

func main () {
    fmt.Println("whats up! don't forget to like this article <3")
}

此時此刻,您必須開始分解您的依賴項/套件以避免它。

TLDR:不要在會被多次載入的地方匯入同一個套件。

7. 延後這個,延後那個……但是,什麼是延後?

我沒有查,但這是我第一次在程式語言中看到保留字 defer。而且由於它不是「通用保留字」的一部分,所以我整整忽略了它!

然後,我的一位同事 Dusan 在看到我在 Go 語言上掙扎了幾個小時後,給我上了一堂 Go 語言的記憶體管理課。 (是的,這是一個大聲喊叫:p)

事情是:每當你打開某個東西的緩衝區/連接時,你應該關閉它!我記得2014年我使用MapleStory伺服器(Java)時,最常見的問題是記憶體洩漏,只是因為開發人員沒有關閉與資料庫的連線。

這可以忘記!但是透過Code Review就不行了哈哈

這是一個 Java 範例:

mkdir go-fodase
cd go-fodase

# go mod init <module-name>
go mod init github.com/danielhe4rt/go-fodase

在編寫 Golang 程式碼時,他們提供了這個延遲屬性,以便您記住在開啟內容後立即將其關閉。

Defer 代表“尊重”,這是在程式碼的特定部分執行結束後“清理”資源的一種方式。

# folder: ~/go-fodase
cat go.mod

# module github.com/danielhe4rt/gofodase
# 
# go 1.23.2

您還可以在一個函數內有多個延遲,並且 DEFER ORDER 很重要!如果您延遲 database2 然後推遲 database1,兩個進程都將以相同的順序進行清理。

go mod tidy

這是一個非常簡單的方法不會搞砸防止你的專案出現記憶體洩漏。請記住在您直播任何內容時使用它。

8.菜鳥錯誤管理

錯誤處理首先類似於:檢查您正在使用的函數是否返回錯誤類型並每次時間驗證它!這是我正在談論的範例:

# go run <your-main-file>

# Environment 1
# .
# ├── go.mod
# └── main.go
go run app.go

# Environment 2
# .
# ├── go.mod
# └── src
#     └── main.go
go run src/app.go

說實話,我討厭這種文法。然而,它是語言的一部分,並且是您在編碼期間會遇到的東西。

有錯誤的函數可能會回傳錯誤或 (T, error),幸運的是 Go 不會讓你忘記這一點。

package main

import(
    "fmt"
)

func main () {
    fmt.Println("whats up! don't forget to like this article <3")
}

用 err != nil 向你的程式碼發送垃圾郵件,我保證你會沒事的! :D

9. 結論壯舉:低延遲程式碼挑戰

除了為了了解環境而付出的所有壓力和時間之外,與我的 Twitch 觀眾一起學習一門新語言是一個很酷的挑戰。他們中的許多人長期以來一直要求我檢查一下,我們就在這裡。

所有這些都反映了我個人在這門語言上的發展經歷,目的是分享我在這兩週的學習過程中所經歷的事情。

9.1 獎勵:程式設計挑戰

最近,我的隊友要求我完成 ScyllaDB 挑戰,它教會了我很多關於並行性、池和速率限制的知識。這是許多公司為了讓自己的產品表現更好而面臨的挑戰!

挑戰的目標是創建一個小型 Go 命令列應用程序,將一些隨機資料插入 ScyllaDB,同時限制請求數量。

您可以在這裡找到儲存庫挑戰:github.com/basementdevs/throtdling-requests-scylla-test。我們還招人呢!您可以在我們的職業部分找到空缺職位!

感謝您的閱讀!我希望這篇文章能為學習 Golang 提供有價值的見解。歡迎分享您的想法或經驗。

以上是這就是我在兩週內學到的關於 Go 的全部內容!的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn