探索Goroutine:Go語言的併發魔法

更新於 發佈於 閱讀時間約 8 分鐘
raw-image

👨‍💻簡介

在日常生活中,如果能同時做很多事情,效率肯定大大提升,那麼在Go語言中,該如何做到呢,答案就是今天的主角Goroutine了,在Go語言中,讓併發變得簡單的強大工具,今天就是來給他一個快速介紹。

什麼是Goroutine?

首先,讓我們以一個簡單的方式來解釋什麼是Goroutine。Goroutine是Go語言的一個特別的功能,它就像是小型的工作任務,可以讓我們同時處理很多事情,而不需要浪費太多電腦資源。可以把它想像成比傳統方式更聰明的方式來處理多項工作,而不會讓電腦變得超級忙碌。這種功能讓Go語言在處理大量同時執行的工作時變得非常強大。

如何創建和啟動Goroutine

要使用Goroutine很簡單,只需要創建一個函數,然後使用go關鍵字在要使用goroutine的函數前面就完成了。可以看以下範例:

package main

import (
"fmt"
)
func main() {
go sayHello()
// 主程式不會等待Goroutine完成
}
func sayHello() {
fmt.Println("Hello, Goroutine!")
}

在這個例子中,我們使用go關鍵字啟動一個新的Goroutine,Goroutine執行了sayHello函數。但須注意,主程式main不會等待Goroutine完成,所以可能不會看到有印出任何東西來。

可以稍微讓main主程式睡一下,就可以看到輸出了

package main

import (
"fmt"
"time"
)
func main() {
go sayHello()
time.Sleep(1)
}
func sayHello() {
fmt.Println("Hello, Goroutine!")
}

Goroutine的執行過程

下面提供了一個簡單的小程式,在主程式裡有兩個goroutine,試著執行一下程式可以發現輸出是一段一段的,會是0跟1交錯印出,代表兩邊的goroutine會搶著印出,呈現競爭狀態

package main

import (
"fmt"
"time"
)
func main() {
go print1()
go print2()
time.Sleep(time.Second)
}
func print1() {
for i := 0; i < 100; i++ {
fmt.Print("0")
}
}
func print2() {
for i := 0; i < 100; i++ {
fmt.Print("1")
}
}

Goroutine之間的通信

併發往往涉及到多個任務之間的通信。這就是通道(Channel)的用武之地。通道是一種特殊的資料結構,用於在不同的Goroutine之間傳遞資料:

package main

import (
"fmt"
"time"
)
func main() {
ch := make(chan string)
go sendData(ch)
go receiveData(ch)
time.Sleep(2 * time.Second) // 等待Goroutines完成
}
func sendData(ch chan string) {
ch <- "Hello from Goroutine!"
}
func receiveData(ch chan string) {
msg := <-ch
fmt.Println(msg)
}

在這個例子中,我們先創建了一個通道ch,然後使用通道在兩個Goroutine之間傳遞消息。 通道的溝通可以看到範例,<- chan 代表將資料從channel中取出,而chan <- 則代表將資料放進channel

Goroutine同步與等待

通常情況下,我們希望主程式能夠等待所有的Goroutine完成,以確保結果的完整性。這就是WaitGroup的作用:

sync.WaitGroup

這個函數的主要功能是讓主程式等待所有的Goroutine完成,然後再繼續執行接下來的程式,主要有以下幾種方法

  • Add(delta int):用來增加計數器的值,表示有多少個Goroutine需要等待。
  • Done():用來減少計數器的值,表示一個Goroutine已經完成。通常在Goroutine執行完後使用 Done
  • Wait():用來將計數器歸零。當計數器的值為零時,Wait 函數會返回,並允許主程式繼續執行。

接著讓我們來看一下範例:

package main

import (
"fmt"
"sync"
)
func main() {
// 創建一個WaitGroup
var wg sync.WaitGroup
// 啟動5個Goroutine
for i := 0; i < 5; i++ {
wg.Add(1) // 增加計數器
go worker(i, &wg)
}
wg.Wait() // 等待所有Goroutines完成
fmt.Println("All Goroutines have finished.")
}
func worker(id int, wg *sync.WaitGroup) {
defer wg.Done() // 減少計數器
fmt.Printf("Worker %d is done\n", id)
}

可以看到,我們使用WaitGroup來等待所有的Goroutine完成,確保我的主程式可以完整執行而不會提前退出。

Goroutine 的特性與限制

特性

  1. 資源消耗極低:Goroutine 的創建相對輕量,主要消耗少量stack空間。這意味著你可以創建大量的 goroutine 而不必擔心資源耗盡的問題。
  2. 有效的線程管理:當一個 goroutine 被阻塞時,相應的管理線程將被擱置,但運行時會將其他 goroutine 分配給這個線程,使其繼續執行其他工作。這種機制確保了線程的高效使用,避免了資源浪費。
  3. 最大線程數限制:你可以透過設定 $GOMAXPROCS 來限制系統中的線程數量,確保它們不會無節制地增加。這有助於避免系統資源的過度消耗。

限制

  1. Goroutine 數量限制:理論上,Go 語言可以創建極多的 Goroutine,但實際上,系統的可用資源(記憶體和 CPU)是有限的。因此,你需要謹慎控制 Goroutine 的數量,以避免過多的併發造成資源耗盡或性能下降。
  2. 競爭條件和死鎖:Goroutine 的併發操作需要謹慎處理共享資源,否則可能出現競爭條件(race condition)和死鎖(deadlock)。這不是直接的限制,但是在 Goroutine 的設計和使用中需要特別注意,以確保程式的正確性。

小結

相信學習Go語言的各位,也是被Goroutine強大的併發能力所吸引,Goroutine還有許多細節,今天這篇只是簡單介紹Goroutine,之後會再慢慢深入探討Goroutine的奧妙之處。

📚Reference

留言
avatar-img
留言分享你的想法!
avatar-img
Alan的開發者天地
18會員
83內容數
golang
Alan的開發者天地的其他內容
2023/10/04
👨‍💻 簡介 最近想要透過小實作來撰寫筆記,達到做中學的效果,因此就來實作個小爬蟲順便結合前面學到的package做一個小複習。
Thumbnail
2023/10/04
👨‍💻 簡介 最近想要透過小實作來撰寫筆記,達到做中學的效果,因此就來實作個小爬蟲順便結合前面學到的package做一個小複習。
Thumbnail
2023/09/28
👨‍💻簡介 今天來介紹一個自己開發後端蠻常用的一個 package,promptui,拿來做menu真的很方便,promptui有兩個主要的輸入模式: Prompt:跳出單行使用者輸入。 Select:提供一個選項列表供使用者選擇。
Thumbnail
2023/09/28
👨‍💻簡介 今天來介紹一個自己開發後端蠻常用的一個 package,promptui,拿來做menu真的很方便,promptui有兩個主要的輸入模式: Prompt:跳出單行使用者輸入。 Select:提供一個選項列表供使用者選擇。
Thumbnail
2023/09/26
👨‍💻 簡介 在處理string時,正則表達式是一個非常有用的工具。Go語言的regexp package 可以使用正則表達式,用來執行如檢查string是否匹配某個模式、提取匹配的subString等操作。
Thumbnail
2023/09/26
👨‍💻 簡介 在處理string時,正則表達式是一個非常有用的工具。Go語言的regexp package 可以使用正則表達式,用來執行如檢查string是否匹配某個模式、提取匹配的subString等操作。
Thumbnail
看更多
你可能也想看
Thumbnail
TOMICA第一波推出吉伊卡哇聯名小車車的時候馬上就被搶購一空,一直很扼腕當時沒有趕緊入手。前陣子閒來無事逛蝦皮,突然發現幾家商場都又開始重新上架,價格也都回到正常水準,估計是官方又再補了一批貨,想都沒想就立刻下單! 同文也跟大家分享近期蝦皮購物紀錄、好用推薦、蝦皮分潤計畫的聯盟行銷!
Thumbnail
TOMICA第一波推出吉伊卡哇聯名小車車的時候馬上就被搶購一空,一直很扼腕當時沒有趕緊入手。前陣子閒來無事逛蝦皮,突然發現幾家商場都又開始重新上架,價格也都回到正常水準,估計是官方又再補了一批貨,想都沒想就立刻下單! 同文也跟大家分享近期蝦皮購物紀錄、好用推薦、蝦皮分潤計畫的聯盟行銷!
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
👨‍💻 簡介 在處理string時,正則表達式是一個非常有用的工具。Go語言的regexp package 可以使用正則表達式,用來執行如檢查string是否匹配某個模式、提取匹配的subString等操作。
Thumbnail
👨‍💻 簡介 在處理string時,正則表達式是一個非常有用的工具。Go語言的regexp package 可以使用正則表達式,用來執行如檢查string是否匹配某個模式、提取匹配的subString等操作。
Thumbnail
👨‍💻簡介 要處理日期和時間,就必須知道這個Package -> time,Go提供了內建的timePackage。 今天主要介紹time的功能,包括時間操作、格式化等等,以及常見用法。
Thumbnail
👨‍💻簡介 要處理日期和時間,就必須知道這個Package -> time,Go提供了內建的timePackage。 今天主要介紹time的功能,包括時間操作、格式化等等,以及常見用法。
Thumbnail
👨‍💻簡介 昨天講到Goroutine的橋梁aka傳話筒 — Channel,那要怎麼知道對方有收到訊息,我的紙條有送到對方手上呢? 今天就是要來介紹幾種Goroutine的確定完成工作的幾種方式。
Thumbnail
👨‍💻簡介 昨天講到Goroutine的橋梁aka傳話筒 — Channel,那要怎麼知道對方有收到訊息,我的紙條有送到對方手上呢? 今天就是要來介紹幾種Goroutine的確定完成工作的幾種方式。
Thumbnail
👨‍💻簡介 昨天講到Goroutine有稍微簡單介紹Channel,Channel是Go語言中極為重要的併發通訊機制,它就像是不同goroutines之間的話筒,允許它們安全地傳遞資料和信息。這個強大的工具使得Go語言在處理併發任務時非常優雅和高效。
Thumbnail
👨‍💻簡介 昨天講到Goroutine有稍微簡單介紹Channel,Channel是Go語言中極為重要的併發通訊機制,它就像是不同goroutines之間的話筒,允許它們安全地傳遞資料和信息。這個強大的工具使得Go語言在處理併發任務時非常優雅和高效。
Thumbnail
👨‍💻簡介 在日常生活中,如果能同時做很多事情,效率肯定大大提升,那麼在Go語言中,該如何做到呢,答案就是今天的主角Goroutine了,在Go語言中,讓併發變得簡單的強大工具,今天就是來給他一個快速介紹。
Thumbnail
👨‍💻簡介 在日常生活中,如果能同時做很多事情,效率肯定大大提升,那麼在Go語言中,該如何做到呢,答案就是今天的主角Goroutine了,在Go語言中,讓併發變得簡單的強大工具,今天就是來給他一個快速介紹。
Thumbnail
👨‍💻簡介 當我們在寫程式時,有時候會需要在程式結束時關閉某些資源,而defer這個關鍵字,可以讓你輕鬆的實現,下面來簡單介紹一下defer以及常用的範例。,它為程式設計師提供了一種簡單而強大的工具,用於管理資源和確保程式的正確執行。
Thumbnail
👨‍💻簡介 當我們在寫程式時,有時候會需要在程式結束時關閉某些資源,而defer這個關鍵字,可以讓你輕鬆的實現,下面來簡單介紹一下defer以及常用的範例。,它為程式設計師提供了一種簡單而強大的工具,用於管理資源和確保程式的正確執行。
Thumbnail
👨‍💻簡介 在 Go 語言中,函數(Function)是一個強大且重要的概念,就像食譜一樣,告訴你應該如何處理食材,最後得到一道美味的料理。經過哪些程序讓程式更有組織性和可讀性。函數可幫助你將程式碼區塊組織成可重複使用的元件,進而執行特定的任務。
Thumbnail
👨‍💻簡介 在 Go 語言中,函數(Function)是一個強大且重要的概念,就像食譜一樣,告訴你應該如何處理食材,最後得到一道美味的料理。經過哪些程序讓程式更有組織性和可讀性。函數可幫助你將程式碼區塊組織成可重複使用的元件,進而執行特定的任務。
Thumbnail
👨‍💻簡介 在這篇文章裡,會簡單介紹幾個關鍵的基本概念和語法結構,加快上手這門程式語言。
Thumbnail
👨‍💻簡介 在這篇文章裡,會簡單介紹幾個關鍵的基本概念和語法結構,加快上手這門程式語言。
Thumbnail
Golang(Go)是由Google開發的一種開源的、靜態型別的編程語言,目的在提供一個簡單、高效、安全以及易於擴展的程式語言,特別適用於並發和平行處理,Go語言設計上著重於開發者的生產力,並提供了現代化的語法和豐富的標準庫。 強調簡單易讀,讓我們回歸原始以最簡易的方式來撰寫程式,併發的特性讓日趨
Thumbnail
Golang(Go)是由Google開發的一種開源的、靜態型別的編程語言,目的在提供一個簡單、高效、安全以及易於擴展的程式語言,特別適用於並發和平行處理,Go語言設計上著重於開發者的生產力,並提供了現代化的語法和豐富的標準庫。 強調簡單易讀,讓我們回歸原始以最簡易的方式來撰寫程式,併發的特性讓日趨
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News