golang基础--chan

了解chan

在 Go(Golang)中,chan 是用来实现 goroutine 之间通信的管道(Channel)。它允许你在线程之间安全地传递数据。

创建chan

go 复制代码
chOne := make(chan int) // 创建一个整型的无缓冲 Channel
chTwo := make(chan string, 2) // 创建一个字符串的缓冲 Channel,容量为 2

发送和接收数据

无缓冲的 Channel 在发送或接收时会阻塞,直到另一端准备好。

go 复制代码
ch := make(chan int)

// 发送数据到 Channel
go func() {
    fmt.Println("1秒后向chan发送数据")
    time.Sleep(1 * time.Second)
    ch <- 1
}()

// 从 Channel 接收数据
fmt.Println("main等待接收数据")
data := <-ch
fmt.Println(data) // 输出: 1
fmt.Println("结束进程")

运行结果 带缓冲的chan

  • 缓冲 Channel 可以存储有限数量的数据,而不需要立即被消费。
  • 如果缓冲已满,发送操作会阻塞,直到缓冲中有空位。
go 复制代码
ch := make(chan int, 2)

ch <- 1
fmt.Println("这里不会阻塞")
ch <- 2

fmt.Println(<-ch) // 输出: 1
fmt.Println(<-ch) // 输出: 2

运行结果

使用 select 语句

select 用于同时监听多个 Channel 的读写操作。

go 复制代码
ch1 := make(chan int)
ch2 := make(chan string)

go func() {
    ch1 <- 1
}()
go func() {
    ch2 <- "Hello"
}()

select {
case msg := <-ch1:
    fmt.Println("接收到数据 ch1:", msg)
case msg := <-ch2:
    fmt.Println("接收到数据 ch2:", msg)
default:
    fmt.Println("无数据")
}
  • select可以同时监听多个ch,上面代码中,那个先接收到数据就执行那个case
  • 如果有default,ch1,ch2为空的情况下,执行default 不堵塞
  • 如果没有default,ch1,ch2为空的情况下,select 会堵塞,直到ch1或ch2任何一个有值
  • 直接使用select{} 不设置任何case,也会导致当前方法堵塞

运行结果

ps : 这个结果是随机的,取决那个case先接收到数据,如果两个go协程没有先于select执行,也就是ch1,ch2还没有值,就执行default 无数据

关闭 Channel

使用 close() 关闭 Channel,表示没有更多数据会发送到这个 Channel。

  • 关闭 Channel 后再发送数据会导致 panic。
  • 从已关闭的 Channel 接收数据会返回零值。
  • 可以通过接收第二个值来检测 Channel 是否已关闭。
go 复制代码
ch := make(chan int)

go func() {
    for i := 0; i < 3; i++ {
       time.Sleep(1 * time.Second)
       ch <- i
    }
    close(ch) // 关闭 Channel
}()

for val := range ch { // 使用 range 读取 Channel,直到关闭
    fmt.Println(val)
}

// chan的第二个值可以判断chan是否被关闭,类似map取值
chHas := make(chan int)
close(chHas)

val, ok := <-chHas
fmt.Println(val, ok) // 输出: 0 false
fmt.Println("程序结束")

运行结果

使用场景

  • 数据流传递:goroutine 之间传递数据。
  • 任务协调:通过 Channel 来同步任务。
  • 信号通知:通过关闭 Channel 实现广播信号。

通过 chan 和 select,可以轻松实现高并发任务的同步和数据通信,是 Go 并发编程的核心之一。

相关推荐
码事漫谈11 小时前
黄仁勋被裁第一天,就收到了橄榄枝
后端
金銀銅鐵12 小时前
带您看懂字节码指令(二):空循环里有什么
java·后端·ai编程
皮皮林55113 小时前
比 Xshell 还好用的 SSH 客户端神器,MobaXterm 太爱了!
后端
我不会起名字32214 小时前
会话缓存失效排查:区分 Redis 失效与节点广播
redis·后端·go·即时通讯·im·故障排查
深入云栈15 小时前
Netty 4.2.x 源码深度解析 (二十三):ByteBuf 核心设计 —— 索引、类型与零拷贝
java·后端·架构
JackJiang15 小时前
IM踩坑:聊天消息ID怎么设计?一个UUID搞不定,我用双ID解决
后端·架构
开心猴爷16 小时前
iOS 上架 App 流程
后端·ios
code_Bo16 小时前
不只命令行:我把跨 Agent 会话同步做成了桌面应用
前端·javascript·后端
用户83562907805117 小时前
使用 Python 控制 Excel 工作表的分页位置
后端·python
用户83562907805117 小时前
Python 如何在 Word 中添加和管理文档变量
后端·python