详解Go语言中select语句的常见用法

 更新时间:2023年07月19日 08:30:37   作者:AlwaysBeta  
这篇文章主要是来和大家介绍一下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 语句中使用任意类型的条件表达式,只能对通道进行操作。

使用规则

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

  • select 语句只能用于通道操作,用于在多个通道之间进行选择,以监听通道的就绪状态,而不是用于其他类型的条件判断。
  • select 语句可以包含多个 case 子句,每个 case 子句对应一个通道操作。当其中任意一个通道就绪时,相应的 case 子句会被执行。
  • 如果多个通道都已经就绪,select 语句会随机选择一个通道来执行。这样确保了多个通道之间的公平竞争。
  • 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.

超时处理

通过结合 select 和 time.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.")
    }
}

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

输出:

Timeout occurred.

以上就是详解Go语言中select语句的常见用法的详细内容,更多关于Go语言select的资料请关注脚本之家其它相关文章!

相关文章

  • go语言定时器Timer及Ticker的功能使用示例详解

    go语言定时器Timer及Ticker的功能使用示例详解

    这篇文章主要为大家介绍了go语言定时器的功能使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2022-04-04
  • Go语言中的字符串处理方法示例详解

    Go语言中的字符串处理方法示例详解

    Go语言的字符串是使用UTF-8编码的。UTF-8是Unicode的实现方式之一。这篇文章主要介绍了Go语言中的字符串处理方法,需要的朋友可以参考下
    2018-10-10
  • 重学Go语言之如何使用Modules

    重学Go语言之如何使用Modules

    Go语言在Go.1.11版本发布了Go Modules,这是一种新的Go项目依赖管理解决方案,可以让Go项目的依赖包关系更加清晰,也更容易管理,下面就来看看Modules是如何使用的吧
    2023-07-07
  • Go语言操作数据库及其常规操作的示例代码

    Go语言操作数据库及其常规操作的示例代码

    这篇文章主要介绍了Go语言操作数据库及其常规操作的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • Go语言并发模型的2种编程方案

    Go语言并发模型的2种编程方案

    这篇文章主要介绍了Go语言并发模型的2种编程方案,本文给出共享内存和通过通信的2种解决方案,并给出了实现代码,需要的朋友可以参考下
    2014-10-10
  • Golang文件读写操作详情

    Golang文件读写操作详情

    这篇文章主要介绍了Golang文件读写操作详情,文件是数据源(保存数据的地方)的一种,文件最主要的作用就是保存数据,文件在程序中是以流的形式来操作的,更多详细内容需要的朋友可以参考一下
    2022-07-07
  • 剖析Go编写的Socket服务器模块解耦及基础模块的设计

    剖析Go编写的Socket服务器模块解耦及基础模块的设计

    这篇文章主要介绍了Go的Socket服务器模块解耦及日志和定时任务的模块设计,举了一些Go语言编写的服务器模块的例子,需要的朋友可以参考下
    2016-03-03
  • 示例剖析golang中的CSP并发模型

    示例剖析golang中的CSP并发模型

    这篇文章主要为大家介绍了示例剖析golang中的CSP并发模型,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • go语言制作分页器实例探究

    go语言制作分页器实例探究

    这篇文章主要为大家介绍了go语言制作分页器实例探究,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • Golang 中实现 Set的思路详解

    Golang 中实现 Set的思路详解

    本文介绍了Go中两种set的实现原理,并在此基础介绍了对应于它们的两个包简单使用,本文介绍的非常详细,需要的朋友参考下吧
    2024-01-01

最新评论