Go并發編程實戰:深入理解Goroutine與Channel

Go并發編程實戰:深入理解Goroutine與Channel

  • Go并發編程實戰:深入理解Goroutine與Channel
    • 概述
    • 1. 為什么是Go的并發?從“線程”與“協程”說起
    • 2. Goroutine:如何使用?
    • 3. Channel:Goroutine間的安全通信
      • 創建與使用
      • 緩沖與同步
      • 經典模式:Range和Close
    • 4. 實戰項目:構建一個并發Web爬蟲
      • 核心功能
      • 代碼實現
      • 如何運行
    • 5. 延伸學習與資源推薦

Go并發編程實戰:深入理解Goroutine與Channel

概述

Go語言(Golang)憑借其簡潔的語法、強大的標準庫和原生支持的并發模型,在現代軟件開發中占據了重要地位,尤其在云計算、微服務和網絡服務后端領域。其最引人注目的特性莫過于GoroutineChannel,它們提供了一種輕量級、安全且高效的并發編程方式,讓你能輕松構建高性能的并發程序。本文將帶你從入門到實戰,徹底掌握Go的并發哲學。
在這里插入圖片描述

1. 為什么是Go的并發?從“線程”與“協程”說起

在傳統語言(如Java)中,我們使用**線程(Thread)**來實現并發。然而,系統線程創建和上下文切換開銷大,且數量有限(通常一臺機器幾千個),管理和同步(通過鎖)也非常復雜,容易出錯。

Go語言引入了**Goroutine(Go協程)**的概念。它是一種由Go運行時(runtime)管理的輕量級線程。

  • 開銷極低:初始棧很小(約2KB),可以根據需要動態伸縮。你可以輕松創建數十萬甚至上百萬個Goroutine而耗盡內存。
  • 調度高效:Go運行時內置了一個強大的調度器(Scheduler),它在少量系統線程上復用Goroutine。當某個Goroutine發生阻塞(如I/O操作)時,調度器會立刻將其掛起,并在同一個線程上運行其他Goroutine。這一切對開發者透明,極大提高了CPU利用率。

簡單來說,Goroutine讓你可以用同步的方式寫異步的代碼,以極低的成本獲得極高的并發能力。

2. Goroutine:如何使用?

使用Goroutine非常簡單,只需在普通的函數調用前加上關鍵字 go

package mainimport ("fmt""time"
)func say(s string) {for i := 0; i < 3; i++ {time.Sleep(100 * time.Millisecond)fmt.Println(s)}
}func main() {// 在一個新的Goroutine中運行say函數go say("world")// 在主Goroutine中運行say函數say("hello")
}

運行上面的代碼,你會看到"hello"和"world"交錯打印,這表明兩個函數在同時執行。注意:主Goroutine結束后,所有其他Goroutine會立即被終止,因此你可能需要一些同步機制來等待它們完成(如使用sync.WaitGroup)。

3. Channel:Goroutine間的安全通信

Goroutine是并發執行的,它們之間如何安全地傳遞數據和協調工作呢?答案是 Channel(通道)

Channel是一種類型化的管道,你可以通過它用操作符 <- 發送和接收值。

創建與使用

ch := make(chan int) // 創建一個傳遞int類型的通道// 在Goroutine中向通道發送數據
go func() {ch <- 42 // 將42發送到通道ch
}()// 從通道接收數據
value := <-ch
fmt.Println(value) // 輸出: 42

緩沖與同步

默認通道是**無緩沖(Unbuffered)的:發送操作會一直阻塞,直到有另一個Goroutine執行接收操作,這是一種強大的同步機制。
你也可以創建
帶緩沖(Buffered)**的通道:

ch := make(chan int, 2) // 緩沖區大小為2
ch <- 1
ch <- 2
// ch <- 3 // 如果此時再發送,就會阻塞,因為緩沖區滿了fmt.Println(<-ch) // 1
fmt.Println(<-ch) // 2

經典模式:Range和Close

發送者可以通過close函數關閉通道,表示沒有更多值會被發送。接收者可以使用range循環來持續接收值,直到通道被關閉。

func fibonacci(n int, c chan int) {x, y := 0, 1for i := 0; i < n; i++ {c <- xx, y = y, x+y}close(c) // 關閉通道
}func main() {c := make(chan int, 10)go fibonacci(cap(c), c)// 使用range循環從通道中接收數據,直到通道被關閉for i := range c {fmt.Println(i)}
}

4. 實戰項目:構建一個并發Web爬蟲

讓我們利用所學知識,構建一個簡單的、并發安全的Web爬蟲。它的功能是并發地抓取一組URL,并統計每個頁面的大小。

核心功能

  • 并發地發送HTTP GET請求獲取多個URL的內容。
  • 使用Channel來收集結果。
  • 使用WaitGroup來等待所有抓取任務完成。

代碼實現

package mainimport ("fmt""io""log""net/http""sync""time"
)// FetchResult 用于存放抓取結果
type FetchResult struct {Url  stringSize int64Err  error
}// fetchUrl 抓取單個URL,將結果發送到channel
func fetchUrl(url string, ch chan<- FetchResult, wg *sync.WaitGroup) {defer wg.Done() // 通知WaitGroup,當前Goroutine已完成start := time.Now()resp, err := http.Get(url)if err != nil {ch <- FetchResult{Url: url, Err: err}return}defer resp.Body.Close()body, err := io.ReadAll(resp.Body)if err != nil {ch <- FetchResult{Url: url, Err: err}return}elapsed := time.Since(start)size := int64(len(body))ch <- FetchResult{Url: url, Size: size, Err: nil}log.Printf("Fetched %s (%d bytes) in %s", url, size, elapsed)
}func main() {urls := []string{"https://www.google.com","https://www.github.com","https://www.stackoverflow.com","https://go.dev","https://medium.com",}// 創建一個帶緩沖的Channel存放結果resultCh := make(chan FetchResult, len(urls))// 創建一個WaitGroup來等待所有Goroutine完成var wg sync.WaitGroup// 為每個URL啟動一個Goroutinefor _, url := range urls {wg.Add(1) // WaitGroup計數器+1go fetchUrl(url, resultCh, &wg)}// 啟動一個單獨的Goroutine,等待所有抓取任務完成后關閉Channelgo func() {wg.Wait()close(resultCh)}()// 主Goroutine從Channel中讀取并處理所有結果fmt.Println("\n=== Fetch Results ===")for result := range resultCh {if result.Err != nil {fmt.Printf("Failed to fetch %s: %v\n", result.Url, result.Err)} else {fmt.Printf("Fetched %s: %d bytes\n", result.Url, result.Size)}}
}

如何運行

  1. 將代碼保存為 concurrent_crawler.go
  2. 在終端運行:go run concurrent_crawler.go

這個項目完美展示了如何用Goroutine實現“fork-join”并發模式,如何使用Channel進行通信,以及如何使用WaitGroup進行同步,是Go并發編程的經典范例。

5. 延伸學習與資源推薦

  • 官方資源:

    • The Go Programming Language Tour (Go語言之旅):官方交互式教程,非常適合初學者。
    • Effective Go:編寫優雅、地道的Go代碼的最佳實踐。
  • 經典書籍:

    • 《The Go Programming Language》 (Alan A. A. Donovan & Brian W. Kernighan):被譽為Go語言的“圣經”,深度和廣度俱佳。
  • 進階主題:

    • Context包:用于在Goroutine之間傳遞截止時間、取消信號以及其他請求范圍的值,是構建網絡服務的關鍵。
    • Sync包:提供了基本的同步原語,如互斥鎖(Mutex)、讀寫鎖(RWMutex)等,用于更底層的同步控制。
    • 并發模式:學習select語句、超時控制、管道(Pipeline)、工作池(Worker Pool)等高級模式。

Go的并發模型是其靈魂所在。掌握Goroutine和Channel,你就能充分利用現代多核CPU的優勢,輕松構建出高性能、高可靠性的服務。祝你學習愉快!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/98268.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/98268.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/98268.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2025服貿會“海淀之夜”,點亮“科技”與“服務”底色

2025年9月12日傍晚&#xff0c;北京頤和園&#xff0c;十七孔橋旁&#xff0c;2025年中國國際服務貿易交易會“海淀之夜”如約而至。在“海淀之夜”&#xff0c;科技機構、金融機構、咨詢服務機構、出海服務企業以及跨國企業和國際友人等&#xff0c;將目光聚焦于此。被第三方機…

qt使用camke時,采用vcpkg工具鏈設置VTK的qt模塊QVTKOpenGLNativeWidget

下載:QVTKOpenGLNativeWidget嵌入qt應用中資源-CSDN下載 1.通過vcpkg安裝VTK,目前的VTK里面默認為qt6,如果需要安裝qt5,需要將端口配置進行修改 筆者的vcpkg的vtk端口路徑:D:\vcpkg\ports\vtk portfile.cmake 修改點: #第一處 #file(READ "${CURRENT_INSTALLED_DIR}/sh…

Axios在鴻蒙應用開發中的使用

目錄一、簡介二、安裝與配置三、axios用法1.axios泛型參數(1).第三個泛型參數-約束data請求參數的類型(2).第二個泛型參數-決定后臺返回數據的類型2.axios攔截器3.請求工具封裝統一處理業務狀態碼錯誤統一處理401或404錯誤一、簡介 Axios 是一個基于 Promise 的網絡請求庫&…

第九周文件上傳

文件上傳漏洞 不同的網站要不同的webshell。我們使用是php開發的網站。 一服務器白名單繞過 服務端白名單(Whitelist)是?種安全機制&#xff0c;它只允許預定義的合法元素通過&#xff08;只有有限的元素進入&#xff09;&#xff0c;其他所有內容默認被拒絕。相比黑名單&am…

計算機視覺必讀論文:從經典到前沿

計算機視覺必讀論文:從經典到前沿 一、前言 二、經典論文解讀? 2.1 圖像分類? 2.1.1 《ImageNet Classification with Deep Convolutional Neural Networks》(AlexNet)? 2.1.2 《Very Deep Convolutional Networks for Large-Scale Image Recognition》(VGGNet)? 2.1.…

對比PowerBI的字段參數,QuickBI的已選字段還有改進的空間

對比PowerBI的字段參數&#xff0c;QuickBI的已選字段還有改進的空間 之前分享過QuickBI的已選字段 vs PowerBI的字段參數&#xff0c;QuickBI可以在表格中實現PowerBI的字段參數效果&#xff0c;甚至比PowerBI實現的過程和使用方式更絲滑。 但如果應用到圖形中會怎么樣呢&am…

飛算JavaAI:Java開發新時代的破曉之光

免責聲明&#xff1a;此文章的所有內容皆是本人實驗測評&#xff0c;并非廣告推廣&#xff0c;并非抄襲。如有侵權&#xff0c;請聯系&#xff0c;謝謝&#xff01;【#飛算JavaAl炫技賽】 【#Java開發】摘要&#xff1a;飛算JavaAI作為全球首款聚焦Java的智能開發助手&#xff…

vulntarget-c靶場內網滲透

1. 環境搭建 2.對ubuntu20的滲透 對其進行端口掃描 訪問80端口 發現是laravel框架。版本是v8.78.1 使用 kaili 自帶的msf 進行滲透 search laravel use exploit/multi/php/ignition_laravel_debug_rce執行利用完成檢測 上傳木馬 先將木馬進行base64編碼 <?php eval($_P…

基于大模型多模態的人體體型評估:從“尺碼測量”到“視覺-感受”范式

基于大模型多模態的人體體型評估&#xff1a;從“尺碼測量”到“視覺-感受”范式摘要&#xff1a;傳統體型識別依賴CV骨架/關鍵點與像素量尺&#xff0c;容易受衣物、發型、姿態、光照影響&#xff0c;且“厘米級數值”與穿衣體驗、審美感受之間存在鴻溝。本文提出一種基于大模…

【docker】——docker國內可用的源

不知道哪里來的&#xff0c;但是可以用。1. 解決方案打開配置文件&#xff08;若文件不存在&#xff0c;會自動創建&#xff09; sudo vim /etc/docker/daemon.json將以下內容粘貼進去{"builder": {"gc": {"defaultKeepStorage": "20GB&quo…

【Windows端口管理】快速查看和釋放被系統保留的TCP端口

問題描述在Windows系統開發時&#xff0c;經常遇到端口無法使用的問題。系統會自動保留一系列TCP/UDP端口范圍&#xff0c;導致應用程序無法綁定這些端口。查看所有被保留的端口范圍查看TCP保留端口# 查看所有TCP端口排除范圍 netsh interface ipv4 show excludedportrange pro…

面經匯總(1)

1.介紹C面向對象的三大特性2.介紹常見的排序算法3.介紹TCP/UDP區別4.TCP三次握手四次揮手5.如果四次揮手第四次客戶端的ACK沒有發出去會有什么結果&#xff1f;6.介紹MYSQL的事務7.介紹線程池8.主要的線程池有哪幾種&#xff1f;9.手撕反轉鏈表10.介紹對象存儲以及常見的對象存…

遙感圖像數字水印系統優化方案

遙感圖像數字水印系統優化方案 1. 引言 遙感圖像在現代地理信息系統、環境監測、軍事偵察等領域發揮著重要作用。為了保護遙感圖像的版權和完整性&#xff0c;數字水印技術被廣泛應用。然而&#xff0c;現有的遙感圖像水印方案往往在不可見性、魯棒性和容量之間存在權衡&#x…

鴻蒙高效數據處理框架全攻略:緩存、并行與流式實戰

摘要 在如今的物聯網和智能設備世界里&#xff0c;數據已經成為最關鍵的資源。無論是可穿戴設備、智能家居&#xff0c;還是車載系統&#xff0c;每一秒都會產生大量數據。如果缺少一套高效的數據處理框架&#xff0c;開發者就可能面臨內存溢出、處理延遲大、設備卡頓等問題。本…

零售企業數字化轉型的道、法、術:基于開源AI大模型AI智能名片S2B2C商城小程序的戰略重構

摘要 在數字經濟與消費升級的雙重驅動下&#xff0c;零售企業正經歷從"流量爭奪"到"用戶時間爭奪"的范式轉變。本文以阿里巴巴、京東、萬達三大巨頭的戰略實踐為樣本&#xff0c;結合開源AI大模型、AI智能名片與S2B2C商城小程序的技術特性&#xff0c;提出…

瑞云渲染為電影《731》提供云渲染技術支持,助力影片全球上映

在“九一八事變”94周年這一莊嚴沉重的紀念時刻&#xff0c;抗戰電影《731》&#xff08;海外名&#xff1a;《EVIL UNBOUND》&#xff09;于世界各地上映&#xff0c;激起廣泛的社會反響與深遠的歷史思考。 瑞云渲染&#xff08;Renderbus&#xff09;作為全球領先的云渲染服…

EasyDSS視頻直播RTMP推流技術如何實現多機型的無人機視頻統一直播

在當今這個瞬息萬變的傳媒時代&#xff0c;無人機與推流直播的結合&#xff0c;正以前所未有的方式重塑著信息傳播的邊界。無人機以其獨特的空中視角和靈活的機動性&#xff0c;為直播行業帶來了革命性的變化&#xff0c;而推流直播技術的成熟&#xff0c;則讓這一變化得以實時…

str.maketrans() 方法

str.maketrans() 方法 功能概述 str.maketrans() 是 Python 中字符串對象的一個靜態方法&#xff0c;用于創建一個字符映射轉換表。這個轉換表本質上是一個字典&#xff0c;它定義了字符之間的替換規則&#xff0c;后續可以被 str.translate() 方法使用&#xff0c;以實現字符串…

敏感詞檢測API平臺推薦

敏感詞檢測API平臺推薦 背景簡介 敏感詞檢測用于識別文本中的違規、涉政、涉黃、辱罵等敏感詞&#xff0c;幫助產品在評論、彈幕、客服對話、運營文案、廣告投放等環節實現自動化質檢與合規攔截。市場上主要有兩類服務商&#xff1a; 專業型廠商&#xff1a;聚焦算法與工程落…

Day25_【深度學習(3)—PyTorch使用(6)—張量拼接操作】

張量的拼接操作在神經網絡搭建過程中是非常常用的方法&#xff0c;例如: 在后面將要學習的注意力機制中都使用到了張量拼接。torch.cat 函數可以將兩個張量根據指定的維度拼接起來&#xff0c;不改變數據維度。前提&#xff1a;除了拼接的維度&#xff0c;其他維度一定要相同。…