Go 语言并发编程介绍
Go 语言设计时就考虑了并发编程的需求,提供了轻量级的线程(goroutine)和通道(channel)作为并发编程的基础。以下是 Go 语言并发编程的一些关键概念和特性:
- Goroutine
 定义:Goroutine 是 Go 语言中的轻量级线程,由 Go 运行时管理。
 创建:使用 go 关键字启动一个新的 Goroutine。
 示例:
package main
  import (
      "fmt"
      "time"
  )
  func say(s string) {
      for i := 0; i < 5; i++ {
          time.Sleep(100 * time.Millisecond)
          fmt.Println(s)
      }
  }
  func main() {
      go say("world")
      say("hello")
  }
- Channel
 定义:Channel 是 Goroutine 之间通信的管道,用于在不同的 Goroutine 之间传递数据。
 创建:使用 make 函数创建 Channel。
 类型:Channel 可以是单向的(只能发送或接收)或双向的(可以发送和接收)。
 示例:
import (
      "fmt"
  )
  func sum(s []int, c chan int) {
      sum := 0
      for _, v := range s {
          sum += v
      }
      c <- sum // 将结果发送到 Channel
  }
  func main() {
      s := []int{7, 2, 8, -9, 4, 0}
      c := make(chan int)
      go sum(s[:len(s)/2], c)
      go sum(s[len(s)/2:], c)
      x, y := <-c, <-c // 从 Channel 接收结果
      fmt.Println(x, y, x+y)
  }
- 同步原语
 WaitGroup:用于等待多个 Goroutine 完成。
 Mutex:用于保护共享资源的互斥锁。
 示例:
package main
  import (
      "fmt"
      "sync"
  )
  func main() {
      var wg sync.WaitGroup
      var mu sync.Mutex
      var counter int
      for i := 0; i < 1000; i++ {
          wg.Add(1)
          go func() {
              defer wg.Done()
              mu.Lock()
              counter++
              mu.Unlock()
          }()
      }
      wg.Wait()
      fmt.Println("Counter:", counter)
  }
- 选择语句(Select)
 定义:select 语句用于在多个 Channel 操作之间进行选择。
 示例:
 package main
import (
"fmt"
"time"
)
func main() {
c1 := make(chan string)
c2 := make(chan string)
go func() {
time.Sleep(1 * time.Second)
c1 <- "one"
}()
go func() {
time.Sleep(2 * time.Second)
c2 <- "two"
}()
for i := 0; i < 2; i++ {
select {
case msg1 := <-c1:
fmt.Println("Received:", msg1)
case msg2 := <-c2:
fmt.Println("Received:", msg2)
}
}
}
- 上下文(Context)
 定义:Context 用于在 Goroutine 之间传递请求范围的值、取消信号等。
 示例:
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
done := make(chan bool, 1)
go func(ctx context.Context) {
select {
case <-ctx.Done():
fmt.Println("Context canceled:", ctx.Err())
done <- true
case <-time.After(2 * time.Second):
fmt.Println("Task completed")
done <- true
}
}(ctx)
<-done
}