程序员求职经验分享与学习资料整理平台

网站首页 > 文章精选 正文

Go语言零到一:管道(channel)(go管道 数据结构)

balukai 2025-07-14 14:49:50 文章精选 3 ℃

引言

管道(channel)是 Go 语言中用于协程(goroutine) 间通信的主要机制。它允许 goroutine 以安全的方式发送和接收数据。

channel 概念

  • 通信管道
    • channel 是一种类型化的通信管道,用于 goroutine 之间的数据交换。
    • 示例:ch := make(chan int)
  • 发送数据
    • 使用 ch <- value 向 channel 发送数据。
    • 示例:ch <- 42
  • 接收数据
    • 使用 value := <-ch 从 channel 接收数据。
    • 示例:value := <-ch
  • 双向通信
    • channel 默认是双向的,既可以从 channel 发送也可以接收数据。
    • 示例:
ch := make(chan int) 
ch <- 1 
value := <-ch
  • 缓冲 channel
    • 可以创建带有缓冲区的 channel,用于存储一定数量的数据项。
    • 示例:
ch := make(chan int, 10) // 创建一个容量为 10 的缓冲 channel

channel 基本用法

  • 创建 channel
    • 使用 make 函数创建一个 channel。
    • 示例:
ch := make(chan int)
  • 发送数据
    • 使用 ch <- value 向 channel 发送数据。
    • 示例:
ch <- 42
  • 接收数据
    • 使用 value := <-ch 从 channel 接收数据。
    • 示例:
value := <-ch
  • 缓冲 channel
    • 创建带有缓冲区的 channel,用于存储一定数量的数据项。
    • 示例:
ch := make(chan int, 10) // 创建一个容量为 10 的缓冲 channel 
ch <- 1 
ch <- 2
  • 关闭 channel
    • 使用 close(ch) 关闭 channel。
    • 示例:
close(ch)
  • 检测 channel 是否关闭
    • 使用 value, ok := <-ch 检测 channel 是否关闭。
    • 示例:
value, ok := <-ch 
if !ok { 
 fmt.Println("Channel closed") 
}

编码实践

// https://go.dev/play/p/B7bCQUfaaRZ
package main

import (
  "fmt"
  "sync"
  "time"
)

func sendData(ch chan int) {
  for i := 0; i < 10; i++ {
    ch <- i
    time.Sleep(100 * time.Millisecond)
  }
  close(ch)
}

func main() {
  // 创建 channel
  ch := make(chan int)

  // 启动 goroutine 来发送数据
  go sendData(ch)

  // 在主 goroutine 中接收数据
  var wg sync.WaitGroup
  wg.Add(1)
  go func() {
    defer wg.Done()
    for value := range ch {
      fmt.Println("Received:", value)
    }
    fmt.Println("Channel closed")
  }()
  wg.Wait()
}

channel 的高级用法

  • 选择通信
    • 使用 select 语句来选择从多个 channel 中接收数据。
    • 示例:
select { 
case value := <-ch1: 
 fmt.Println("Received from ch1:", value) 
case value := <-ch2: 
 fmt.Println("Received from ch2:", value) 
}
  • 非阻塞通信
    • 使用 select 语句或直接发送/接收来实现非阻塞通信。
    • 示例:
select { 
case ch <- value: 
 fmt.Println("Sent value") 
default: 
 fmt.Println("Channel full") 
}
  • 多路复用
    • 使用多个 channel 和 select 语句来实现多路复用。
    • 示例:
select { 
case ch1 <- 1: 
case ch2 <- 2: 
}

Tags:

最近发表
标签列表