【go 】 select case 的用法
相关文章:
【go】select 语句case的随机性
【go】 select case 超时机制(time.After)示例和内存泄漏
1. 基本使用:监听多个通道,会阻塞
特点:
1)case 只能一次性的,一旦响应后,就结束了,参见后面第三章节for的例子,可以多次监听
2)如果多个通道都没有响应,会阻塞,直到某个通道率先响应
package main
import (
"fmt"
"time"
)
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
// 启动两个 goroutine 发送数据
go func() {
time.Sleep(2 * time.Second)
ch1 <- "Message from ch1"
}()
go func() {
time.Sleep(1 * time.Second)
ch2 <- "Message from ch2"
}()
// 使用 select 等待任意一个通道的消息
select {
case msg1 := <-ch1:
fmt.Println("Received:", msg1)
case msg2 := <-ch2:
fmt.Println("Received:", msg2)
}
}
输出示例:
Received: Message from ch2
2.带默认分支:非阻塞操作
select 可以配合 default 分支进行非阻塞操作。
当其他的case不满足条件时,就一定会走到default分支,不会阻塞
package main
import "fmt"
func main() {
ch := make(chan string)
select {
case msg := <-ch:
fmt.Println("Received:", msg)
default:
fmt.Println("No message received, doing something else...")
}
}
输出:
No message received, doing something else...
3. 永远监听多个通道
用 for-select 模式可以实现对多个通道的持续监听。
package main
import (
"fmt"
"time"
)
/*
*
模拟一直监听
*/
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
go func() {
for {
time.Sleep(2 * time.Second)
ch1 <- "Ping"
}
}()
go func() {
for {
time.Sleep(3 * time.Second)
ch2 <- "Pong"
}
}()
for {
select {
case msg := <-ch1:
fmt.Println("Received from ch1:", msg)
case msg := <-ch2:
fmt.Println("Received from ch2:", msg)
}
}
}
4. 超时机制
详情参见 【go】 select case 超时机制(time.After)示例和内存泄漏
配合 time.After 可以实现超时控制。
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan string)
// 启动一个 goroutine,模拟长时间处理
go func() {
time.Sleep(3 * time.Second)
ch <- "Result"
}()
select {
case res := <-ch:
fmt.Println("Received:", res)
case <-time.After(2 * time.Second):
fmt.Println("Timeout!")
}
}
输出:
Timeout!
5. 关闭通道的处理
当通道关闭时,select 中接收操作会立即
返回零值。
注意:当通道被关闭后,不是阻塞的,而是立即返回一个0值。 这里的0值是指长度为0的字符串,不是数字0
package main
import "fmt"
func main() {
ch := make(chan int)
go func() {
ch <- 42
close(ch)
}()
select {
case val, ok := <-ch:
if !ok { //利用ok来判断是否通道是关闭的
fmt.Println("Channel closed!")
} else {
fmt.Println("Received:", val)
}
}
}
6. context的关闭判断
有时候利用上下文,我们可以实现一些功能,并且需要判断上下文是否关闭,也可以通过select case
package main
import (
"context"
"fmt"
"time"
)
func worker(ctx context.Context, id int) {
select {
case <-ctx.Done():
fmt.Printf("Worker %d: canceled\n", id)
case <-time.After(2 * time.Second):
fmt.Printf("Worker %d: completed\n", id)
}
}
func main() {
// 创建父 context
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// 子 context
subCtx1, cancel1 := context.WithTimeout(ctx, 1*time.Second)
defer cancel1()
subCtx2, cancel2 := context.WithTimeout(ctx, 3*time.Second)
defer cancel2()
go worker(subCtx1, 1)
go worker(subCtx2, 2)
// 模拟某种条件触发取消
time.Sleep(2 * time.Second)
cancel() // 取消父 context,影响所有子 context
time.Sleep(2 * time.Second)
fmt.Println("Main function exits")
}
原文地址:https://blog.csdn.net/m0_45406092/article/details/144259541
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!