当前位置: 首页 > article >正文

【go从零单排】通道select、通道timeout、Non-Blocking Channel Operations非阻塞通道操作

挪威特罗姆瑟夜景

🌈Don’t worry , just coding!
内耗与overthinking只会削弱你的精力,虚度你的光阴,每天迈出一小步,回头时发现已经走了很远。

📗概念

select 语句是 Go 的一种控制结构,用于等待多个通道操作。它类似于 switch 语句,但用于通道的接收和发送

超时是指在一定时间内未能完成某项操作(如接收通道消息或发送消息),从而采取某种措施(如执行默认操作或返回错误)

非阻塞通道操作是指通过 select 语句的 default 分支,或者直接在通道操作中,尝试发送或接收数据而不会导致 goroutine 阻塞。

💻代码

通道select

package main

import (
	"fmt"
	"time"
)

func main() {
	c1 := make(chan string) // 创建一个字符串类型的通道 c1
	c2 := make(chan string) // 创建一个字符串类型的通道 c2

	// 启动第一个 goroutine
	go func() {
		time.Sleep(1 * time.Second) // 暂停 1 秒
		c1 <- "one"                 // 向 c1 通道发送消息 "one"
	}()

	// 启动第二个 goroutine
	go func() {
		time.Sleep(2 * time.Second) // 暂停 2 秒
		c2 <- "two"                 // 向 c2 通道发送消息 "two"
	}()

	// 循环接收消息
	for i := 0; i < 2; i++ {
		select {
		case msg1 := <-c1: // 从 c1 通道接收消息
			fmt.Println("received", msg1) // 打印接收到的消息
		case msg2 := <-c2: // 从 c2 通道接收消息
			fmt.Println("received", msg2) // 打印接收到的消息
		}
	}
}

//输出
//启动等待一秒后打印 received one
//启动等待2秒后打印 received two,因为两个等待是同时执行的,所以总执行时间是2秒

通道timeout

package main

import (
	"fmt"
	"time"
)

func main() {
	c1 := make(chan string, 1) // 创建一个缓冲通道 c1,容量为 1
	go func() {
		time.Sleep(2 * time.Second) // 暂停 2 秒
		c1 <- "result 1"            // 向 c1 通道发送 "result 1"
	}()

	// 第一个 select 语句
	select {
	case res := <-c1: // 尝试从 c1 接收消息
		fmt.Println(res) // 打印接收到的消息
	case <-time.After(1 * time.Second): // 如果 1 秒后还没有消息,则执行此 case
		fmt.Println("timeout 1") // 打印超时消息
	}

	c2 := make(chan string, 1) // 创建另一个缓冲通道 c2,容量为 1
	go func() {
		time.Sleep(2 * time.Second) // 暂停 2 秒
		c2 <- "result 2"            // 向 c2 通道发送 "result 2"
	}()

	// 第二个 select 语句
	select {
	case res := <-c2: // 尝试从 c2 接收消息
		fmt.Println(res) // 打印接收到的消息
	case <-time.After(3 * time.Second): // 如果 3 秒后还没有消息,则执行此 case
		fmt.Println("timeout 2") // 打印超时消息
	}
}
//输出
//timeout 1
//result 2

Non-Blocking Channel Operations非阻塞通道操作

package main

import "fmt"

func main() {
	messages := make(chan string) // 创建一个字符串类型的通道 messages
	signals := make(chan bool)    // 创建一个布尔类型的通道 signals

	// 第一个 select 语句
	select {
	case msg := <-messages: // 尝试从 messages 通道接收消息
		fmt.Println("received message", msg)
	default: // 如果没有消息可接收,则执行此分支
		fmt.Println("no message received")
	}

	msg := "hi" // 定义消息内容
	// 第二个 select 语句
	select {
	case messages <- msg: // 尝试向 messages 通道发送消息
		fmt.Println("sent message", msg)
	default: // 如果通道满或没有接收者,则执行此分支
		fmt.Println("no message sent")
	}

	// 第三个 select 语句
	select {
	case msg := <-messages: // 尝试从 messages 通道接收消息
		fmt.Println("received message", msg)
	case sig := <-signals: // 尝试从 signals 通道接收信号,这里是bool类型的通道,并没有消息发送进来
		fmt.Println("received signal", sig)
	default: // 如果没有消息或信号可接收,则执行此分支
		fmt.Println("no activity")
	}
}

//输出
//no message received
//no message sent
//no activity
  • 通道可以用 select 语句来处理消息和信号。
  • select 语句的 default 分支允许在没有可用通道操作时执行其他逻辑,避免了阻塞。

🔍理解

  • select 语句可以有效地等待多个通道的操作,确保程序能够及时响应来自不同通道的消息
  • 通过使用 time.Sleep 模拟耗时操作,可以并发执行的特性。
  • time.After 用于设置超时机制,确保程序不会无限期等待通道的消息。
  • select 语句的 default 分支允许在没有可用通道操作时执行其他逻辑,避免了阻塞。

💪无人扶我青云志,我自踏雪至山巅。
在这里插入图片描述


http://www.kler.cn/a/390194.html

相关文章:

  • Bugku CTF_Web——文件上传
  • GIS空间分析案例---城市公共设施配置与服务评价
  • Vue 项目打包后环境变量丢失问题(清除缓存),区分.env和.env.*文件
  • DNS面临的4大类共计11小类安全风险及防御措施
  • 浅谈C#之内存管理
  • SAP_MM_SD_PP_FICO_视频课程几乎免费送
  • CNN实现地铁短时客流预测
  • 解非线性方程
  • 【MPC-Simulink】EX03 基于非线性系统线性化模型MPC仿真(MIMO)
  • 光流法(Optical Flow)
  • 云岚到家 秒杀抢购
  • VCSVerdi:KDB文件的生成和导入
  • QT Unknown module(s) in QT 以及maintenance tool的更详细用法(qt6.6.0)
  • P1打卡-使用Pytorch实现mnist手写数字识别
  • 解锁高效直播新体验:第三代 AI 手机自动直播工具,开启直播高效运作新时代!
  • 网页web无插件播放器EasyPlayer.js点播播放器遇到视频地址播放不了的现象及措施
  • 设计模式(主要的五种)
  • 软件设计师 - 层次化存储
  • 大数据-216 数据挖掘 机器学习理论 - KMeans 基于轮廓系数来选择 n_clusters
  • 鸿蒙UI开发——小图标的使用
  • 使用API有效率地管理Dynadot域名,列表形式查看账户whois联系人信息
  • Dubbo负载均衡
  • Baget 私有化nuget
  • SpringBoot助力企业资产优化
  • Matlab实现鹈鹕优化算法(POA)求解路径规划问题
  • [Docker#4] 镜像仓库 | 部分常用命令