原文链接: Go 语言 select 都能做什么?

在 Go 语言中,select 是一个关键字,用于监听和 channel 有关的 IO 操作。

通过 select 语句,我们可以同时监听多个 channel,并在其中任意一个 channel 就绪时进行相应的处理。

本文将总结一下 select 语句的常见用法,以及在使用过程中的注意事项。

基本语法

select 语句的基本语法如下:

select {
case <-channel1:
// 通道 channel1 就绪时的处理逻辑
case data := <-channel2:
// 通道 channel2 就绪时的处理逻辑
default:
// 当没有任何通道就绪时的默认处理逻辑
}

看到这个语法,很容易想到 switch 语句。

虽然 select 语句和 switch 语句在表面上有些相似,但它们的用途和功能是不同的。

switch 用于条件判断,而 select 用于通道操作。不能在 select 语句中使用任意类型的条件表达式,只能对通道进行操作。

使用规则

虽然语法简单,但是在使用过程中,还是有一些地方需要注意,我总结了如下四点:

  1. select 语句只能用于通道操作,用于在多个通道之间进行选择,以监听通道的就绪状态,而不是用于其他类型的条件判断。
  2. select 语句可以包含多个 case 子句,每个 case 子句对应一个通道操作。当其中任意一个通道就绪时,相应的 case 子句会被执行。
  3. 如果多个通道都已经就绪,select 语句会随机选择一个通道来执行。这样确保了多个通道之间的公平竞争。
  4. select 语句的执行可能是阻塞的,也可能是非阻塞的。如果没有任何一个通道就绪且没有默认的 default 子句,select 语句会阻塞,直到有一个通道就绪。如果有 default 子句,且没有任何通道就绪,那么 select 语句会执行 default 子句,从而避免阻塞。

多路复用

select 最常见的用途之一,同时监听多个通道,并根据它们的就绪状态执行不同的操作。

package main

import (
"fmt"
"time"
) func main() {
c1 := make(chan string)
c2 := make(chan string) go func() {
time.Sleep(3 * time.Second)
c1 <- "one"
}() go func() {
time.Sleep(3 * time.Second)
c2 <- "two"
}() select {
case msg := <-c1:
fmt.Println(msg)
case msg := <-c2:
fmt.Println(msg)
}
}

执行上面的代码,程序会随机打印 one 或者 two,如果通道为空的话,程序就会一直阻塞在那里。

非阻塞通信

当通道中没有数据可读或者没有缓冲空间可写时,普通的读写操作将会阻塞。

但通过 select 语句,我们可以在没有数据就绪时执行默认的逻辑,避免程序陷入无限等待状态。

package main

import (
"fmt"
) func main() {
channel := make(chan int) select {
case data := <-channel:
fmt.Println("Received:", data)
default:
fmt.Println("No data available.")
}
}

执行上面代码,程序会执行 default 分支。

输出:

No data available.

超时处理

通过结合 selecttime.After 函数,我们可以在指定时间内等待通道就绪,超过时间后执行相应的逻辑。

package main

import (
"fmt"
"time"
) func main() {
channel := make(chan int) select {
case data := <-channel:
fmt.Println("Received:", data)
case <-time.After(3 * time.Second):
fmt.Println("Timeout occurred.")
}
}

执行上面代码,如果 channel3 秒内没有数据可读,select 会执行 time.After 分支。

输出:

Timeout occurred.

以上就是本文的全部内容,如果觉得还不错的话欢迎点赞转发关注,感谢支持。


推荐阅读:

Go 语言 select 都能做什么?的更多相关文章

  1. PHP语言学习之php做图片上传功能

    本文主要向大家介绍了PHP语言学习之php做图片上传功能,通过具体的内容向大家展示,希望对大家学习php语言有所帮助. 今天来做一个图片上传功能的插件,首先做一个html文件:text.php < ...

  2. MySQL 使用SELECT ... FOR UPDATE 做事务写入前的确认(转)

    Select…For Update语句的语法与select语句相同,只是在select语句的后面加FOR UPDATE [NOWAIT]子句. 该语句用来锁定特定的行(如果有where子句,就是满足w ...

  3. [语法]C语言中二维数组做输入参数

    C语言中二维数组做输入参数时, 可以同时指定各维长度, 可以只指定第二维的长度, 不可以只指定第一维的长度, 不可以各维长度都不指定. 一句话总结:要指定至少指定第二维,都不指定是不行的. 具体栗子如 ...

  4. NodeJS什么都能做,为什么还要JAVA?

    这张图看起来简单而且很好理解,但没尝试过,会有很多疑问. SPA模式中,后端已供了所需的数据接口,view前端已经可以控制,为什么要多加NodeJS这一层? 多加一层,性能怎么样? 多加一层,前端的工 ...

  5. Java 程序员每天都在做什么?

    作为一名 在大.中.小微企业都待过 的 Java 开发者,今天和大家分享下自己在不同公司的工作日常和收获.包括一些个人积累的工作提升经验,以及一些 Java 学习的方法和资源. 先从我的第一份 Jav ...

  6. 微信小程序来了,小程序都能做些什么

    2017年的微信大动作就是微信小程序了,到底小程序都能做些什么?这是很多人关注的热点,小程序开发对企业又有什么帮助呢?下面让厦门微信小程序开发公司来为你就分析下.       微信小程序与APP的关系 ...

  7. 腾讯QQ会员技术团队:人人都可以做深度学习应用:入门篇(下)

    四.经典入门demo:识别手写数字(MNIST) 常规的编程入门有"Hello world"程序,而深度学习的入门程序则是MNIST,一个识别28*28像素的图片中的手写数字的程序 ...

  8. linux c语言 select函数用法

    linux c语言 select函数用法 表头文件 #i nclude<sys/time.h> #i nclude<sys/types.h> #i nclude<unis ...

  9. 【腾讯Bugly干货分享】人人都可以做深度学习应用:入门篇

    导语 2016年,继虚拟现实(VR)之后,人工智能(AI)的概念全面进入大众的视野.谷歌,微软,IBM等科技巨头纷纷重点布局,AI 貌似将成为互联网的下一个风口. 很多开发同学,对人工智能非常感兴趣, ...

  10. Muduo学习笔记(一) 什么都不做的EventLoop

    Muduo学习笔记(一) 什么都不做的EventLoop EventLoop EventLoop的基本接口包括构造.析构.loop(). One Loop Per Thread 一个线程只有一个Eve ...

随机推荐

  1. [双目视差] 单双目MATLAB 相机标定(二)双目摄像机标定

    文章目录 单双目MATLAB 相机标定(二)双目摄像机标定 一.环境准备 二.标定过程 单双目MATLAB 相机标定(二)双目摄像机标定 一.环境准备 MATLAB R2014a+windows7 6 ...

  2. 【必知必会的MySQL知识】mysql5.7安装教程

    1.下载mysql 下载地址:https://dev.mysql.com/downloads/mysql/5.7.html#downloads 下载zip免安装版,可以省去很多事 2.将下载的安装文件 ...

  3. Docker compose单机编排工具

    Docker compose单机编排工具 目录 Docker compose单机编排工具 docker-compose介绍 Docker Compose使用的三步: docker-compose安装部 ...

  4. autojs系列-js入门1

    开头 确保 Autojs 和 adb 还有模拟器安装调试完成之后,就可以进行js的学习了 调试安装一部分步骤可以参考 https://www.cnblogs.com/c-keke/p/14919615 ...

  5. vue全家桶进阶之路17:组件与组件间的通信

    在 Vue2 中,组件与组件之间的通信可以通过以下几种方式来实现: Props 和 Events 这是 Vue2 中最基础和常用的父子组件通信方式.父组件通过属性传递数据给子组件,子组件通过事件触发向 ...

  6. Python encode()方法和decode()方法

    Python encode()方法 encode() 方法为字符串类型(str)提供的方法,用于将 str 类型转换成 bytes 类型,这个过程也称为"编码".encode() ...

  7. 玩转服务器之网站篇:新手使用WordPress搭建博客和静态网站部署

    静态网站部署和WordPress搭建博客都是网站运营中常见的工作.静态网站是一种不需要服务器端脚本的网站形式,通常使用HTML.CSS和JavaScript等静态资源进行构建和显示.而WordPres ...

  8. ORM核心功能之导航属性- EFCore和 SqlSugar

    导航属性 导航属性是作为ORM核心功能中的核心,在SqlSugar没有支持导航属性前,都说只是一个高级DbHelper, 经过3年的SqlSugar重构已经拥有了一套 非常成熟的导航属性体系,本文不是 ...

  9. js递归生成树形结构

    先看结果 结果 [ { "id": 1, "title": "张三", "parent_id": -1, "c ...

  10. Pytorch-如何在模型中引入可学习参数

    错误实例: def init(self): self.w1 = torch.nn.Parameter(torch.FloatTensor(1),requires_grad=True).cuda() s ...