Go语言WaitGroup和Channel介绍 | 青训营

64 阅读3分钟

1. WaitGroup概述

WaitGroup是Go语言标准库sync包中的一个类型,用于等待一组goroutine完成。通过调用Add方法增加等待的goroutine数量,通过调用Done方法减少等待的goroutine数量,调用Wait方法阻塞主goroutine,直到等待的goroutine数量为0。

2. WaitGroup使用场景

  • 适用于需要等待一组goroutine执行完毕才能继续执行后面的逻辑的场景
  • 适用于需要在多个goroutine之间同步执行完毕的场景

3. WaitGroup常用方法

WaitGroup的常用方法包括:

  • Add(delta int):增加等待的goroutine数量,delta为增加的数量。
  • Done():减少等待的goroutine数量。
  • Wait():阻塞主goroutine,直到等待的goroutine数量为0。

4. WaitGroup示例代码

以下是一些示例代码:

  • 示例代码1:使用WaitGroup等待一组goroutine执行完毕
package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func(i int) {
            defer wg.Done()
            fmt.Printf("goroutine %d finished\n", i)
        }(i)
    }
    wg.Wait()
    fmt.Println("all goroutines finished")
}
  • 示例代码2:使用WaitGroup实现goroutine的同步执行
package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup
    wg.Add(2)
    go func() {
        defer wg.Done()
        fmt.Println("goroutine 1 finished")
    }()
    go func() {
        defer wg.Done()
        fmt.Println("goroutine 2 finished")
    }()
    wg.Wait()
    fmt.Println("all goroutines finished")
}

5. WaitGroup注意事项

在使用WaitGroup时需要注意以下几点:

  • 在调用Wait之前,不要忘记调用Done方法减少等待的goroutine数量,否则可能导致Wait永远阻塞。
  • 在调用Wait时,如果等待的goroutine数量已经为0,则Wait会立即返回,不会阻塞主goroutine。

1. GoChannel概述

Go Channel是Go语言中用于实现并发通信的一种机制。它是类型安全且可进行类型推断的,常用于在goroutines之间进行数据传输。

2. Go Channel使用场景

  • 适用于需要在goroutines之间进行安全的数据传输的场景
  • 适用于需要同步多个goroutines的场景

3. Go Channel常用操作

Go Channel的常用操作包括:

  • make(chan T)创建一个T类型的Channel
  • <-操作符用于发送和接收数据
  • len(ch)获取Channel的缓冲区中的元素数量
  • close(ch)关闭Channel

4. Go Channel示例代码

以下是一些示例代码:

  • 示例代码1:使用Channel进行数据传输
package main

import "fmt"

func main() {
    ch := make(chan int)
    go func() {
        ch <- 42 // 发送数据到Channel
    }()
    fmt.Println(<-ch) // 从Channel接收数据并打印
}
  • 示例代码2:使用Channel实现goroutine的同步执行
package main

import "fmt"

func main() {
    ch := make(chan struct{}) // 创建一个无缓冲的Channel
    go func() {
        fmt.Println("goroutine 1 finished")
        ch <- struct{}{} // 发送信号到Channel
    }()
    go func() {
        fmt.Println("goroutine 2 finished")
        ch <- struct{}{} // 发送信号到Channel
    }()
    <-ch // 从Channel接收信号并等待,直到两个goroutine都执行完毕
    fmt.Println("all goroutines finished")
}

5. Go Channel注意事项

在使用Go Channel时需要注意以下几点:

  • 在接收数据之前,必须先发送数据,否则可能导致阻塞。
  • 在发送和接收数据时,必须确保对应的Channel是可用的,否则可能导致数据丢失或出现竞争条件。