百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

select...case语句详解 selectcase语句用法

yuyutoo 2024-10-12 01:41 25 浏览 0 评论

select 语句

select 语句类似于 switch 语句, 但是select会随机执行一个可运行的case。如果没有case可运行, 它将阻塞, 直到有case可运行。

select 是Go中的一个控制结构, 类似于用于通信的switch语句。每个case必须是一个通信操作, 要么是发送要么是接收。

select 随机执行一个可运行的case。如果没有case可运行, 它将阻塞, 直到有case可运行。一个默认的子句应该总是可运行的。

语法:

select {
    case communication clause :
    statement(s);
    case communication clause :
    statement(s);
    /* 你可以定义任意数量的 case */
    default : /* 可选 */
    statement(s);
}

以下描述了 select 语句的语法:

每个case都必须是一个通信

所有channel表达式都会被求值

所有被发送的表达式都会被求值

如果任意某个通信可以进行, 它就执行;其他被忽略。

如果有多个case都可以运行, Select会随机公平地选出一个执行。其他不会执行。

否则:

如果有default子句, 则执行该语句。

如果没有default字句, select将阻塞, 直到某个通信可以运行;Go不会重新对channel或值进行求值。


package main
import "fmt"
func main() {
    var c1, c2, c3 chan int
    var i1, i2 int
    select {
    case i1 = <-c1:
    fmt.Printf("received ", i1, " from c1\n")
    case c2 <- i2:
    fmt.Printf("sent ", i2, " to c2\n")
    case i3, ok := (<-c3): // same as: i3, ok := <-c3
    if ok {
    fmt.Printf("received ", i3, " from c3\n")
    } else {
    fmt.Printf("c3 is closed\n")
    }
    default:
    fmt.Printf("no communication\n")
    }
}

以上代码执行结果为:

no communication

select可以监听channel的数据流动

select的用法与switch语法非常类似, 由select开始的一个新的选择块, 每个选择条件由case语句来描述

与switch语句可以选择任何使用相等比较的条件相比, select由比较多的限制, 其中最大的一条限制就是每个case语句里必须是一个IO操作

select { //不停的在这里检测
case <-chanl : //检测有没有数据可以读
//如果chanl成功读取到数据,则进行该case处理语句
case chan2 <- 1 : //检测有没有可以写
//如果成功向chan2写入数据,则进行该case处理语句


//假如没有default,那么在以上两个条件都不成立的情况下,就会在此阻塞//一般default会不写在里面,select中的default子句总是可运行的,因为会很消耗CPU资源
default:
//如果以上都没有符合条件,那么则进行default处理流程
}

在一个select语句中, Go会按顺序从头到尾评估每一个发送和接收的语句。

如果其中的任意一个语句可以继续执行(即没有被阻塞), 那么就从那些可以执行的语句中任意选择一条来使用。

如果没有任意一条语句可以执行(即所有的通道都被阻塞), 那么有两种可能的情况:

1 如果给出了default语句, 那么就会执行default的流程, 同时程序的执行会从select语句后的语句中恢复。

2 如果没有default语句, 那么select语句将被阻塞, 直到至少有一个case可以进行下去。

Golang select的使用及典型用法

基本使用

select是Go中的一个控制结构, 类似于switch语句, 用于处理异步IO操作。select会监听case语句中channel的读写操作, 当case中channel读写操作为非阻塞状态(即能读写)时,将会触发相应的动作。

select中的case语句必须是一个channel操作

select中的default子句总是可运行的。

如果有多个case都可以运行, select会随机公平地选出一个执行, 其他不会执行。

如果没有可运行的case语句, 且有default语句, 那么就会执行default的动作。

如果没有可运行的case语句, 且没有default语句, select将阻塞, 直到某个case通信可以运行

例如:

package main
import "fmt"
func main() {
var c1, c2, c3 chan int
var i1, i2 int
select {
case i1 = <-c1:
fmt.Printf("received ", i1, " from c1\n")
case c2 <- i2:
fmt.Printf("sent ", i2, " to c2\n")
case i3, ok := (<-c3): // same as: i3, ok := <-c3
if ok {
fmt.Printf("received ", i3, " from c3\n")
} else {
fmt.Printf("c3 is closed\n")
}
default:
fmt.Printf("no communication\n")
}
}
//输出:no communication

典型用法

1.超时判断

//比如在下面的场景中,使用全局resChan来接受response,如果时间超过3S,resChan中还没有数据返回,则第二条case将执行

package main
import (
"fmt"
"time"
)
var resChan = make(chan int)
// do request
func main() {
select {
case data := <-resChan:
doData(data)
case <-time.After(time.Second * 3): // 超时判断
fmt.Println("request time out")
}
}
func doData(data int) {
fmt.Println(data)
}

2.退出

//主线程(协程)中如下:
var shouldQuit=make(chan struct{})
fun main(){
{
//loop
}
//...out of the loop
select {
case <-c.shouldQuit:
cleanUp()
return
default:
}
//...
}
//再另外一个协程中,如果运行遇到非法操作或不可处理的错误,就向shouldQuit发送数据通知程序停止运行
close(shouldQuit)

3.判断channel是否阻塞

//在某些情况下是存在不希望channel缓存满了的需求的,可以用如下方法判断
ch := make (chan int, 5)
//...
data:=0
select {
case ch <- data:
default:
//做相应操作,比如丢弃data。视需求而定
}

4 select...case 匹配多个通道问题?

package main
import (
"fmt"
"time"
)
func main() {
timeout := make(chan bool, 1)
ch := make(chan int)
go func() {
time.Sleep(1 * time.Second)
timeout <- true
}()
go func() {
time.Sleep(13 * time.Second)
ch <- 1
}()
// select...case 专门用于匹配通道
select {
// 这里是匹配两个通道, 是分开执行的,不是匹配两个值的效果(不同于PHP、js的语法效果)
case <-ch:
// fmt.Println("ch 通道")
case <-timeout:
fmt.Println("timeout!")
}
/*
// select case 无法匹配两个通道, 是错误的语法
// switch...case 可以匹配多个值(非通道)
select{
case <-ch, <-timeout:
fmt.Println("timeout")
}
*/
}

相关推荐

Python操作Word文档神器:python-docx库从入门到精通

Python操作Word文档神器:python-docx库从入门到精通动动小手,点击关注...

Python 函数调用从入门到精通:超详细定义解析与实战指南 附案例

一、函数基础:定义与调用的核心逻辑定义:函数是将重复或相关的代码块封装成可复用的单元,通过函数名和参数实现特定功能。它是Python模块化编程的基础,能提高代码复用性和可读性。定义语法:...

等这么长时间Python背记手册终于来了,入门到精通(视频400集)

本文毫无套路!真诚分享!前言:无论是学习任何一门语言,基础知识一定要扎实,基础功非常的重要,找一个有丰富编程经验的老师或者师兄带着你会少走很多弯路,你的进步速度也会快很多,无论我们学习的目的是什么,...

图解Python编程:从入门到精通系列教程(附全套速查表)

引言本系列教程展开讲解Python编程语言,Python是一门开源免费、通用型的脚本编程语言,它上手简单,功能强大,它也是互联网最热门的编程语言之一。Python生态丰富,库(模块)极其丰富,这使...

Python入门教程(非常详细)从零基础入门到精通,看完这一篇就够

本书是Python经典实例解析,采用基于实例的方法编写,每个实例都会解决具体的问题和难题。主要内容有:数字、字符串和元组,语句与语法,函数定义,列表、集、字典,用户输入和输出等内置数据结构,类和对象,...

Python函数全解析:从入门到精通,一文搞定!

1.为什么要用函数?函数的作用:封装代码,提高复用性,减少重复,提高可读性。...

Python中的单例模式:从入门到精通

Python中的单例模式:从入门到精通引言单例模式是一种常用的软件设计模式,它保证了一个类只有一个实例,并提供一个全局访问点。这种模式通常用于那些需要频繁创建和销毁的对象,比如日志对象、线程池、缓存等...

【Python王者归来】手把手教你,Python从入门到精通!

用800个程序实例、5万行代码手把手教你,Python从入门到精通!...

Python从零基础入门到精通:一个月就够了

如果想从零基础到入门,能够全职学习(自学),那么一个月足够了。...

Python 从入门到精通:一个月就够了

要知道,一个月是一段很长的时间。如果每天坚持用6-7小时来做一件事,你会有意想不到的收获。作为初学者,第一个月的月目标应该是这样的:熟悉基本概念(变量,条件,列表,循环,函数)练习超过30个编...

Python零基础到精通,这8个入门技巧让你少走弯路,7天速通编程!

Python学习就像玩积木,从最基础的块开始,一步步搭建出复杂的作品。我记得刚开始学Python时也是一头雾水,走了不少弯路。现在回头看,其实掌握几个核心概念,就能快速入门这门编程语言。来聊聊怎么用最...

神仙级python入门教程(非常详细),从0到精通,从看这篇开始!

python入门虽然简单,很多新手依然卡在基础安装阶段,大部分教程对一些基础内容都是一带而过,好多新手朋友,对一些基础知识常常一知半解,需要在网上查询很久。...

Python类从入门到精通,一篇就够!

一、Python类是什么?大家在生活中应该都见过汽车吧,每一辆真实存在、能在路上跑的汽车,都可以看作是一个“对象”。那这些汽车是怎么生产出来的呢?其实,在生产之前,汽车公司都会先设计一个详细的蓝图...

学习Python从入门到精通:30天足够了,这才是python基础的天花板

当年2w买的全套python教程用不着了,现在送给有缘人,不要钱,一个月教你从入门到精通1、本套视频共487集,本套视频共分4季...

30天Python 入门到精通(3天学会python)

以下是一个为期30天的Python入门到精通学习课程,专为零基础新手设计。课程从基础语法开始,逐步深入到面向对象编程、数据处理,最后实现运行简单的大语言模型(如基于HuggingFace...

取消回复欢迎 发表评论: