偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Golang并發(fā)模型:何時(shí)該用Goroutine?何時(shí)該用Channel?

開發(fā) 前端
Goroutine最佳實(shí)踐總是考慮Goroutine的退出機(jī)制,使用sync.WaitGroup來等待Goroutine完成,避免創(chuàng)建無限制的Goroutine(考慮工作池模式),為Goroutine添加恢復(fù)機(jī)制(defer + recover)


引言

  • 簡要介紹Golang的并發(fā)模型
  • Goroutine和Channel的基本概念
  • 為什么需要理解它們的使用時(shí)機(jī)

第一部分:Goroutine的使用場景

1. 執(zhí)行獨(dú)立任務(wù)時(shí)

// 示例:并發(fā)執(zhí)行多個(gè)獨(dú)立HTTP請求
func fetchURL(url string, wg *sync.WaitGroup){
    defer wg.Done()
    resp, err := http.Get(url)
    if err !=nil{
        fmt.Printf("Error fetching %s: %v\n", url, err)
        return
    }
    fmt.Printf("Fetched %s, status: %s\n", url, resp.Status)
}

func main(){
    urls :=[]string{"https://golang.org","https://google.com","https://github.com"}
var wg sync.WaitGroup

    for_, url :=range urls {
        wg.Add(1)
        go fetchURL(url,&wg)
    }

    wg.Wait()
    fmt.Println("All requests completed!")
}

2. 需要并行計(jì)算時(shí)

// 示例:并行計(jì)算斐波那契數(shù)列
func calculateFibonacci(n int, result chan<-int){
    if n <=1{
        result <- n
        return
    }

    a :=make(chanint)
    b :=make(chanint)

    go calculateFibonacci(n-1, a)
    go calculateFibonacci(n-2, b)

    result <-(<-a +<-b)
}

func main(){
    result :=make(chanint)
    go calculateFibonacci(10, result)
    fmt.Printf("Fib(10) = %d\n",<-result)
}

3. 處理I/O密集型操作時(shí)

// 示例:并發(fā)讀取多個(gè)文件
func readFile(filename string, results chan<-string){
    data, err := os.ReadFile(filename)
    if err !=nil{
        results <- fmt.Sprintf("Error reading %s: %v", filename, err)
        return
    }
    results <- fmt.Sprintf("Read %s: %d bytes", filename,len(data))
}

func main(){
    files :=[]string{"file1.txt","file2.txt","file3.txt"}
    results :=make(chanstring,len(files))

    for_, file :=range files {
        go readFile(file, results)
    }

    for range files {
        fmt.Println(<-results)
    }
}

4. 實(shí)現(xiàn)后臺任務(wù)時(shí)

// 示例:后臺日志處理器
func logProcessor(logs <-chanstring){
    for logEntry :=range logs {
    // 模擬處理延遲
        time.Sleep(100* time.Millisecond)
        fmt.Printf("Processed log: %s\n", logEntry)
    }
}

func main(){
    logChan :=make(chanstring,100)
    go logProcessor(logChan)

    // 模擬生成日志
    for i :=0; i <10; i++{
        logChan <- fmt.Sprintf("Log entry %d", i)
    }

    close(logChan)
    time.Sleep(1* time.Second)// 等待處理完成
}

第二部分:Channel的使用場景

1. Goroutine間通信時(shí)

// 示例:生產(chǎn)者-消費(fèi)者模型
func producer(items chan<-int){
    for i :=0; i <5; i++{
        items <- i
        time.Sleep(time.Second)
    }
    close(items)
}

func consumer(id int, items <-chanint){
    for item :=range items {
        fmt.Printf("Consumer %d received: %d\n", id, item)
    }
}

func main(){
    items :=make(chanint)

    go producer(items)

    // 啟動多個(gè)消費(fèi)者
    for i :=1; i <=3; i++{
        go consumer(i, items)
    }

    time.Sleep(6* time.Second)
}

2. 同步Goroutine執(zhí)行時(shí)

// 示例:使用Channel同步多個(gè)Goroutine
func worker(id int, ready <-chanstruct{}, done chan<-int){
    <-ready // 等待開始信號
    fmt.Printf("Worker %d started\n", id)
    time.Sleep(time.Duration(rand.Intn(3))* time.Second)
    fmt.Printf("Worker %d finished\n", id)
    done <- id
}

func main(){
    const numWorkers =5
    ready :=make(chanstruct{})
    done :=make(chanint, numWorkers)

    // 啟動workers
    for i :=1; i <= numWorkers; i++{
    go worker(i, ready, done)
}

// 同時(shí)開始所有workers
close(ready)

// 等待所有workers完成
for i :=1; i <= numWorkers; i++{
    <-done
}

    fmt.Println("All workers completed")
}

3. 實(shí)現(xiàn)管道模式時(shí)

// 示例:數(shù)據(jù)處理管道
func stage1(in <-chan int)<-chan int{
    out :=make(chan int)
    go func(){
    for n :=range in {
            out <- n *2
    }
    close(out)
}()
    return out
}

func stage2(in <-chan int)<-chan int{
    out :=make(chan int)
    go func(){
        for n :=range in {
            out <- n +1
        }
        close(out)
    }()
    return out
}

func stage3(in <-chan int)<-chan string{
    out :=make(chan string)
    go func(){
        for n :=range in {
            out <- fmt.Sprintf("Result: %d", n)
        }
    close(out)
    }()
    return out
}

func main(){
    // 創(chuàng)建輸入channel
    in :=make(chanint)

    // 構(gòu)建管道
    pipeline :=stage3(stage2(stage1(in)))

    // 發(fā)送數(shù)據(jù)
    go func(){
        for i :=0; i <5; i++{
            in <- i
        }
        close(in)
    }()

    // 接收結(jié)果
    for result :=range pipeline {
        fmt.Println(result)
    }
}

4. 限制并發(fā)數(shù)量時(shí)

// 示例:使用緩沖Channel實(shí)現(xiàn)工作池
func worker(id int, jobs <-chan int, results chan<-int){
    for j :=range jobs {
        fmt.Printf("Worker %d started job %d\n", id, j)
        time.Sleep(time.Second)
        fmt.Printf("Worker %d finished job %d\n", id, j)
        results <- j *2
    }
}

func main(){
    const numJobs =10
    const numWorkers =3

    jobs :=make(chanint, numJobs)
    results :=make(chanint, numJobs)

    // 啟動workers
    for w :=1; w <= numWorkers; w++{
        go worker(w, jobs, results)
    }

    // 發(fā)送jobs
    for j :=1; j <= numJobs; j++{
        jobs <- j
    }
    close(jobs)

    // 收集結(jié)果
    for a :=1; a <= numJobs; a++{
        <-results
    }
}

第三部分:Goroutine和Channel的聯(lián)合使用

1. 扇出模式

// 示例:一個(gè)生產(chǎn)者,多個(gè)消費(fèi)者
func producer(nums chan<-int){
    for i :=0; i <10; i++{
        nums <- i
    }
    close(nums)
}

func consumer(id int, nums <-chan int, done chan<-bool){
    for num :=range nums {
        fmt.Printf("Consumer %d got %d\n", id, num)
        time.Sleep(time.Duration(rand.Intn(500))* time.Millisecond)
    }
    done <-true
}

func main(){
    nums :=make(chanint)
    done :=make(chanbool)

    go producer(nums)

    // 啟動多個(gè)消費(fèi)者
    for i :=0; i <3; i++{
    go consumer(i, nums, done)
}

    // 等待所有消費(fèi)者完成
    for i :=0; i <3; i++{
        <-done
    }
}

2. 扇入模式

// 示例:多個(gè)生產(chǎn)者,一個(gè)消費(fèi)者
func producer(id int, nums chan<-int){
    for i :=0; i <3; i++{
        nums <- id*10+ i
        time.Sleep(time.Duration(rand.Intn(500))* time.Millisecond)
    }
}

func consumer(nums <-chanint, done chan<-bool){
    for num :=range nums {
        fmt.Printf("Received: %d\n", num)
    }
    done <-true
}

func main(){
    nums :=make(chanint)
    done :=make(chanbool)

    // 啟動多個(gè)生產(chǎn)者
    for i :=0; i <3; i++{
        go producer(i, nums)
    }

    // 啟動消費(fèi)者
    go func(){
        time.Sleep(2* time.Second)
        close(nums)
    }()
    go consumer(nums, done)

    <-done
}

3. 超時(shí)控制

// 示例:使用select實(shí)現(xiàn)超時(shí)控制
func longRunningTask(result chan<-string){
    // 模擬長時(shí)間運(yùn)行的任務(wù)
    time.Sleep(3* time.Second)
    result <-"Task completed"
}

func main(){
    result :=make(chanstring)
    go longRunningTask(result)

    select{
        case res :=<-result:
            fmt.Println(res)
        case<-time.After(2* time.Second):
            fmt.Println("Task timed out")
    }
}

第四部分:最佳實(shí)踐與常見陷阱

Goroutine最佳實(shí)踐

  • 總是考慮Goroutine的退出機(jī)制
  • 使用sync.WaitGroup來等待Goroutine完成
  • 避免創(chuàng)建無限制的Goroutine(考慮工作池模式)
  • 為Goroutine添加恢復(fù)機(jī)制(defer + recover)

Channel最佳實(shí)踐

  • 明確Channel的所有權(quán)(哪個(gè)Goroutine負(fù)責(zé)關(guān)閉)
  • 使用緩沖Channel來解耦生產(chǎn)者和消費(fèi)者
  • 考慮使用context.Context來取消Channel操作
  • 小心nil Channel和已關(guān)閉Channel的操作

常見陷阱

  • Goroutine泄漏
  • Channel死鎖
  • 共享內(nèi)存競爭條件
  • 不正確的Channel關(guān)閉

結(jié)論

  • 總結(jié)Goroutine和Channel的核心使用場景
  • 強(qiáng)調(diào)根據(jù)具體需求選擇合適的并發(fā)模式
  • 推薦進(jìn)一步學(xué)習(xí)資源(官方文檔、經(jīng)典書籍等)
責(zé)任編輯:武曉燕 來源: Go語言圈
相關(guān)推薦

2019-12-06 09:41:40

開源技術(shù) 軟件

2022-07-06 09:29:40

JMH性能測試

2020-10-21 14:54:02

RustGolang開發(fā)

2021-06-29 23:40:19

Golang語言并發(fā)

2021-12-19 23:58:51

Golang語言返回值

2017-05-15 09:55:07

2020-05-12 11:25:50

MySQLES數(shù)據(jù)庫

2021-11-26 09:00:00

數(shù)據(jù)庫數(shù)據(jù)集工具

2021-04-12 07:34:03

Java集合框架

2011-08-08 15:43:01

MySQL索引

2021-09-30 09:21:28

Go語言并發(fā)編程

2025-08-11 08:05:58

MCP服務(wù)工具

2019-11-29 07:53:07

DNSTCP網(wǎng)絡(luò)協(xié)議

2025-03-03 10:13:09

2018-07-10 16:05:05

2021-12-09 09:52:36

云原生安全工具云安全

2020-12-13 14:32:22

5GWi-Fi 6

2024-02-28 11:41:50

2022-05-06 08:00:00

APIBallerina編程語言

2014-12-05 09:49:18

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號