安迪熊

技術、閱讀、生活


  • 首頁

  • 關於

  • 標籤

  • 分類

  • 站點地圖

  • 搜尋

[Go] channel中蘊含的大智慧

發表於 2024-03-08 | 分類於 Go |
字數統計: 4.1k

在探索Go語言的併發模型時,我們會接觸到兩個核心元素:Goroutine和channel。Goroutine是構成Go應用併發架構的基石,而channel則在整個併發模型中扮演了無可替代的角色。透過channel,不僅能夠實現Goroutine之間的數據通信,還能夠達到同步的效果。換句話說,只有當你能夠熟練地運用channel時,才能真正稱得上精通Go的併發設計。

因此,在本篇文章中,我們將詳細學習channel的基本語法及其在實際開發中的應用。

使用channel就像操作普通變數一樣簡單。我們可以定義一個channel類型的變數、對其進行賦值、把channel作為參數傳遞給其他函數或方法,甚至可以從函數或方法中return channel作為返回值,或者將一個channel直接發送至另一個channel。這些操作使得channel的應用變得靈活多變,大大提升了開發者在設計和實現併發功能時的便利和效率。

閱讀全文 »

[Go] goroutine是怎麼工作的?

發表於 2024-02-29 | 分類於 Go |
字數統計: 1.4k

在這篇Go中最強的魔法: 併發程式執行的文章中,我們探討了併發的基本概念以及Go語言中實現併發的機制—Goroutine。這些內容對於剛接觸Go的Gopher來說,可以說是入門級的學習資料。

但是,你可能會好奇,既然Go不是採用傳統的基於執行緒的併發模型,那Go的運行時是如何管理和調度(Schedule)眾多Goroutine的呢?實際上,這些是Go語言核心開發團隊的關注點,普通開發者通常不需要深入了解。不過深入理解Goroutine的調度原理對於寫出高效能的Go程式碼是非常有幫助的。

接下來,讓我們一起簡要探索一下Goroutine調度器的工作原理。

Goroutine調度器

閱讀全文 »

[Go] Go中最強的的魔法: 併發程式執行

發表於 2024-02-23 | 分類於 Go |
字數統計: 2.2k

當 Google 工程師設計 Go 語言時,他們明確將多核支援和原生併發支援定為其核心設計目標,同時將併發作為 Go 的設計哲學的一部分。Go 語言一經公開發布,其對併發的原生支援便立刻成為開發者們最為關注的特色之一。

想要掌握 Go 的併發特性,首先需要了解兩個方面:併發的基本概念和 Go 如何實現對併發的支持,包括 goroutine、channel 和 select 等語言特性。

本篇文章將首先介紹 goroutine 的基礎知識及其使用注意事項,讓讀者對 Go 的併發特性有一個初步的認識,之後將進一步深入探討。

閱讀全文 »

[Go] Interface的使用技巧

發表於 2024-02-16 | 分類於 Go |
字數統計: 1.9k

這篇文章要來聊聊如何運用Interface改善我們的程式專案,換句話說,我們講的是Go語言中interface的使用模式和習慣。

首先得強調一點,那就是「適度封裝」。換句話說,我們不是為了封裝而封裝。我們之前提到過,接口其實就是一種封裝的手段,主要目的是為了解耦。所以,重點是我們應該在真正需要的時候才使用接口。

大部分情況下,接口都能對應用設計帶來好處。但如何恰當地使用interface來優化我們的程式設計呢?這就要從Go語言的「組合」設計哲學說起了。

閱讀全文 »

[Go] Interface: 為什麼nil接口不等於nil?

發表於 2024-02-08 | 分類於 Go |
字數統計: 1.3k

Interface 是 Go 這門靜態語言中具有「動靜兼備」特性的語法元素。它既展示了 Go 的強大表達能力,也經常讓初學者感到迷惑。為了釐清這些迷惑,本文將深入探討 Go 在 runtime 時是如何處理 Interface 的類型表現。

在我們揭開 Interface 的神秘面紗之前,先來理解其「動靜兼備」的特性究竟是什麼。

接口的靜態與動態特性

接口的靜態特性主要是指接口類型變數有其靜態類型,例如在 var err error 中,err 的靜態類型為 error。有了這樣的靜態類型,編譯器在編譯階段對所有接口類型變數的賦值進行類型檢查,確保賦值操作的右值實現了該接口的所有方法,否則會報錯:

1
var err error = 1 // cannot use 1 (type int) as type error in assignment: int does not implement error (missing Error method)
閱讀全文 »

[Go] Interface即類型的使用定義

發表於 2024-01-31 | 分類於 Go |
字數統計: 1.9k

在 Go 語言中,interface 是一組方法的集合,透過 type 和 interface 關鍵字來定義。這些方法的集合唯一確定了這個 interface 類型所表示的契約。讓我們來看看一個典型的 interface 類型 MyInterface 的定義:

1
2
3
4
type MyInterface interface {
M1(int) error
M2(io.Writer, ...string)
}

從這個定義中,我們可以看到,interface 類型 MyInterface 包含了兩個方法:M1 和 M2。Go 語言要求 interface 類型聲明中的方法必須是具名的,並且方法名字在這個 interface 類型的方法集合中必須唯一。從 Go 1.14 版本開始,Go 允許嵌入的不同 interface 類型的方法集合存在交集,但前提是交集中的方法不僅名字一樣,連方法簽名(參數列表和返回值列表)也必須一致,否則 Go 編譯器會報錯。

例如,以下示例中 Interface3 嵌入了 Interface1 和 Interface2,但它們之間的 M1 方法簽名不同,導致編譯出錯:

1
2
3
4
5
6
7
8
9
10
11
12
13
type Interface1 interface {
M1()
}
type Interface2 interface {
M1(string)
M2()
}

type Interface3 interface {
Interface1
Interface2 // 編譯器報錯:duplicate method M1
M3()
}
閱讀全文 »

[Go] Method: 怎麼用變數模擬繼承

發表於 2024-01-23 | 分類於 Go |
字數統計: 1.8k

Go 語言的繼承與組合

Go 語言沒有像 C++/Java 等語言可以透過 extend 關鍵字來繼承某個 class。因此,Go class的所有方法都是自己顯式實現的。讓我們舉個例子,自定義class T 有兩個methods M1 和 M2,如果 T 是一個獨立的自定義class,那我們在聲明class T 的 Go 包原始碼文件中一定可以找到其所有method的實現程式碼,比如:

1
2
func (T) M1() {...}
func (T) M2() {...}

在 Go 語言中,如果我們真的想模擬繼承的效果,可以透過 Go 語言設計思想的“組合”來實現。具體的 Go 語言設計思想可以參考我的這篇文章 - Go語言的設計哲學

閱讀全文 »

[Go] Method: Method與如何選擇Receiver類型

發表於 2024-01-17 | 分類於 Go |
字數統計: 1.6k

和多數程式語言一樣,在 Go 語言中,我們需要考慮如何設計方法。由於在 Go 語言中,方法本質上就是函數,所以我們之前講解的關於函數設計的內容同樣適用於方法,例如錯誤處理設計、針對異常的處理策略、使用 defer 提升簡潔性,等等。

Receiver(Receiver)也是設計方法時需要考量的一點。Receiver定義了一個Method所屬的類型,有點類似於其他語言中的 class 或 object 的概念,如下所示:

1
2
func (t T) M1() {}
func (t *T) M2() {}

上面範例中的 t 就是Receiver,而 M1 和 M2 是Receiver定義的Method。M1 方法代表Receiver類型為 T 的Method,而 M2 方法則代表Receiver類型為 *T 的Method。下面我們來看看不同的Receiver類型對 M1 和 M2 的影響。

閱讀全文 »

[Go] Defer的妙用 - 跟蹤函數調用鏈

發表於 2024-01-06 | 分類於 Go |
字數統計: 971

在 Go 語言中,defer 關鍵字是一個強大而且實用的工具,能讓你更優雅地處理資源釋放和一些在函數結束前必須執行的清理工作。本文將通過生動的比喻和簡單的示例,幫助你理解 defer 的使用方法及其重要性。

defer 是什麼?

簡單來說,defer 是用來延遲執行一段程式碼,直到所在的函數即將返回時才執行。就像你在餐廳吃飯,最後才會付錢一樣,defer 讓你在程式的適當位置安排程式碼,但等到適當的時候才執行。

閱讀全文 »

[Go] 搞清楚Go語言的生命週期

發表於 2023-12-27 | 分類於 Go |
字數統計: 2.4k

在剛開始學習 Go 語言的時候,我們可能經常會遇到這樣一個問題:一個 Go 專案中有數十個 Go packages,每個package中又有若干常數、變數、各種函數和方法,那 Go 程式究竟是從哪裡開始執行的呢?後續的執行順序又是什麼樣的呢?

了解這門語言的執行次序,對我們寫出結構合理、邏輯清晰的程式大有助益。無論你使用的是哪種編程範式(Paradigm),過程式的、物件導向的、函數式的,還是其他編程範式,深入了解一下總歸是好的。

今天這篇文章,我就帶你來了解一下 Go 程式的執行次序,這樣在後續閱讀和理解 Go 程式碼的時候,你就好比擁有了“通往寶藏的地圖”,可以直接沿著 Go 程式碼執行次序這張“地圖”去閱讀和理解 Go 程式碼,不會在龐大的程式庫中迷失。

Go 程式由一系列 Go package組成,程式碼的執行也是在各個package之間跳轉。和其他語言一樣,Go 也擁有自己的執行入口 - main 函數。這篇文章我們就從 main 函數入手,逐步展開,最終帶你掌握 Go 程式的執行順序。

閱讀全文 »
<123…7>

68 文章
7 分類
59 標籤
© 2024 Kaichia Chen