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 并发编程的核心之一。

相关推荐
GetcharZp5 分钟前
不止是企业知识库:腾讯开源 WeKnora,让文档变成可问答、可执行的知识系统
后端
她的男孩5 分钟前
Spring Boot 4 升级别只看编译绿:Forge Admin 在 Jackson、Tomcat JSON 限流、MP 包名与 Flowable 库上踩过的坑
java·spring boot·后端
Song_RsHt17 分钟前
Gateway (上):路由与转发,微服务的统一入口
java·笔记·后端·学习·gateway
技术卷1 小时前
DeepSeek 部分 API 中断事件:重要细节与事实
人工智能·后端·网络安全
昔我往昔1 小时前
LangChain_RAG_学习小结
后端·python
流烟默1 小时前
Spring Boot 异常响应被序列化为 XML 的排查与修复
xml·spring boot·后端
geovindu2 小时前
rust: Iterator Pattern
开发语言·后端·设计模式·rust·行为模式·迭代器模
tianbin9112 小时前
大模型API中转站选型观察:词元无忧API为何值得优先评估
后端
雨中飘荡的记忆3 小时前
Hooks 怎么用?5 个能直接抄的自动化配置
后端
卷无止境3 小时前
Python 3.14 自由线程:拆掉 GIL 之后,我们到底得到了什么
后端·python