Golang 通道之 select 语句

2024-01-09 06:46:41

前言

select 语句是一个强大的特性,用于同时等待多个通道操作。select 可以监听多个通道的读写事件,并在有通道准备好时执行相关的case。如果有多个case同时就绪,select 会随机选择一个执行。如果没有case就绪,select 将阻塞,直到至少有一个case就绪。你还可以使用 default case来避免 select 阻塞,它会在其他case都没有就绪时执行

使用

下面是使用 select 语句的一个简单例子:

package main

import (
	"fmt"
	"time"
)

func main() {
	ch1 := make(chan string)
	ch2 := make(chan string)

	go func() {
		time.Sleep(1 * time.Second)
		ch1 <- "one"
	}()

	go func() {
		time.Sleep(2 * time.Second)
		ch2 <- "two"
	}()

	for i := 0; i < 2; i++ {
		select {
		case msg1 := <-ch1:
			fmt.Println("Received", msg1)
		case msg2 := <-ch2:
			fmt.Println("Received", msg2)
		}
	}
}

我们创建了两个通道 ch1 和 ch2,并启动了两个协程分别向这两个通道发送数据。在 main 函数中,select 语句在两个通道上等待数据。根据哪个通道先接收到数据,select 会执行相应的case。由于我们用 for 循环两次,它会打印出两条从通道接收到的消息

Received one
Received two

如果没有 default case,select 会阻塞,直到一个通道准备好。如果添加了 default case,它将不会阻塞:

select {
case msg1 := <-ch1:
    fmt.Println("Received", msg1)
case msg2 := <-ch2:
    fmt.Println("Received", msg2)
default:
    fmt.Println("No messages received")
}

在这种情况下,如果 ch1 和 ch2 都没有消息,立即打印出 “No messages received”

time.After

在 Go 中处理协程的超时,通常会用到 select 语句配合 time.After 函数

time.After 创建一个通道,该通道在指定的时间后会接收到一个时间值。使用 select 语句可以等待多个通道操作,包括这个超时通道

下面是一个例子,展示了如何实现一个超时机制:

package main

import (
	"fmt"
	"time"
)

func main() {
	// 模拟一个将要执行的操作的通道
	operation := make(chan bool)

	// 在协程中模拟一个耗时的操作
	go func() {
		time.Sleep(2 * time.Second) // 模拟耗时
		operation <- true           // 发送操作完成的信号
	}()

	// 使用select来等待操作的完成或超时
	select {
	case result := <-operation:
		// 如果操作完成,执行这个分支
		fmt.Println("Operation finished with result:", result)
	case <-time.After(1 * time.Second):
		// 如果操作超时(1秒后),执行这个分支
		fmt.Println("Operation timed out")
	}
}

如果 operation 通道在 1 秒内接收到消息,会打印出操作完成的信息。如果在指定的超时时间内没有消息,select 将执行与 time.After 关联的 case,并打印出超时信息

因为这里设置的超时时间是 1 秒,而协程中的操作会睡眠 2 秒,所以这个程序将会输出:

Operation timed out

通过调整 time.After 中的时间或协程中的睡眠时间,你可以观察不同的行为。如果操作在超时时间内完成,则会打印结果。否则,将会打印超时信息。这种模式在处理网络请求、数据库操作或任何需要超时保护的场景中非常有用

文章来源:https://blog.csdn.net/e5pool/article/details/135470326
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。