首页 > 其他分享 >Go 语言 select 都能做什么?

Go 语言 select 都能做什么?

时间:2023-07-28 21:12:33浏览次数:37  
标签:语句 main 语言 子句 Go 就绪 select 通道

原文链接: 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.

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


推荐阅读:

标签:语句,main,语言,子句,Go,就绪,select,通道
From: https://www.cnblogs.com/alwaysbeta/p/17588898.html

相关文章

  • 第三章 指针才是C语言的精髓(嵌入式Linux与物联网软件开发 C语言内核深度解析)
    这仅仅是读《嵌入式Linux与物联网软件开发:C语言内核深度解析》pdf的知识记录 地址:指的都是某个字节的地址。比如inta的空间大小有4个字节,每个字节都有一个地址(也就是有4个地址),但是只有首字节地址才能作为整个a空间的地址。也就是说,整个内存以1个字节为基本单位划分无数个地址,......
  • 使用RunnerGo来简化测试流程
    在软件开发过程中,测试是一个重要的环节,需要投入大量时间和精力来确保应用程序或网站的质量和稳定性。但是,随着应用程序变得更加复杂和庞大,传统的测试工具在面对比较繁琐的项目时非常费时费力。这时,一些自动化测试工具就显得尤为重要了。其中,RunnerGo(开源)作为一款性能测试平台,可以帮......
  • Google网站管理员:提升移动Web性…
    移动互联网已经在全球得到了广泛的应用。到2009年,有50%的新增的互联网访问都是来自手机设备的(eMarket,2008和2009)。来自Google的内部资料显示,随着移动浏览器的提升,用户的浏览习惯也在逐步改进。移动浏览器上的页面布局与桌面浏览器有着显著的差异,所以,想要在移动设备上开......
  • golang打印指针切片/数组的值
     FmtSlice2String方法可以将指针切片的值打印处理packagemainimport( "fmt" "reflect")typeStudentstruct{ Namestring`json:"name"cn:"名字"` Ageuint64`json:"age"cn:"年龄"`}funcmain(){ s:=mak......
  • 使用RunnerGo来简化测试流程
    在软件开发过程中,测试是一个重要的环节,需要投入大量时间和精力来确保应用程序或网站的质量和稳定性。但是,随着应用程序变得更加复杂和庞大,传统的测试工具在面对比较繁琐的项目时非常费时费力。这时,一些自动化测试工具就显得尤为重要了。其中,RunnerGo(开源)作为一款性能测试平台,可以......
  • 使用Go调用Powershell加域
    packagemainimport( "fmt" "github.com/go-ldap/ldap/v3" "github.com/mozillazg/go-pinyin" "os" "os/exec" "strings" "time")funcChineseToAbbreviation(chinesestring)string{......
  • Django-4.2博客开发教程:维护后台数据admin模块(六)
    在每个app目录下有个admin.py,使用这个文件可以对其app进行控制。步骤如下:1)先在settings里对其进行注册这里在myblog\myblog\settings.py  > INSTALLED_APPS里把APP名添加进去INSTALLED_APPS=[#'blog.apps.BlogConfig',#注册APP应用'blog','django.co......
  • Golang gRPC学习(05): retry重试
    什么是重试如果服务出现了错误,主要是网络,服务器出现了短暂异常的时候,该怎么办?我们都会人工或者自动的重新连接服务试试,看服务是否恢复可用了。这种重新进行连接服务的一种方式就是重试。如果是在微服务里,应该属于微服务治理的范畴。重试是处理网络服务出现暂时不可用的一种方......
  • 初学C语言day06--进程影响及类型限定符
    进程映像:程序:存储在磁盘上的可执行文件(二进制文件、脚本文件)进程:正在系统中运行的程序进程映像:进程的内存分布情况:text代码段存储二进制指令、常量,只读的,如果强行修改会产生段错误data数据段初始化过的全局变量、初始化过的静态局部变量bss静态数据段未初......
  • 【C语言】二分查找算法
    在⼀个升序的数组中查找制定的数字n,很容易想到的⽅法就是遍历数组,但是这种⽅法效率⽐较低,⽐如我买了⼀双鞋,你好奇问我多少钱,我说不超过300元。你还是好奇,你想知道到底多少,我就让你猜,你会怎么猜?你会1,2,3,4...这样猜吗?显然很慢;⼀般你都会猜中间数字,⽐如:150,然后看⼤了还是⼩了,这就是......