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 实现广播信号。

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

相关推荐
冷琅辞9 分钟前
Go语言的嵌入式网络
开发语言·后端·golang
跟着珅聪学java3 小时前
spring boot +Elment UI 上传文件教程
java·spring boot·后端·ui·elementui·vue
徐小黑ACG4 小时前
GO语言 使用protobuf
开发语言·后端·golang·protobuf
战族狼魂6 小时前
CSGO 皮肤交易平台后端 (Spring Boot) 代码结构与示例
java·spring boot·后端
杉之8 小时前
常见前端GET请求以及对应的Spring后端接收接口写法
java·前端·后端·spring·vue
hycccccch8 小时前
Canal+RabbitMQ实现MySQL数据增量同步
java·数据库·后端·rabbitmq
bobz9659 小时前
k8s 怎么提供虚拟机更好
后端
bobz9659 小时前
nova compute 如何创建 ovs 端口
后端
用键盘当武器的秋刀鱼9 小时前
springBoot统一响应类型3.5.1版本
java·spring boot·后端
Asthenia041210 小时前
从迷宫到公式:为 NFA 构造正规式
后端