go select 使用总结

简介: go select 使用总结

转载请注明出处:

  在Go语言中,select语句用于处理多个通道的并发操作。它类似于switch语句,但是select语句用于通信操作,而不是条件判断。select语句会同时监听多个通道的操作,并选择其中一个可用的通道进行操作。 select语句的语法如下:

select {
    case <-channel1:
        // 执行channel1的操作
    case data := <-channel2:
        // 执行channel2的操作,同时将通道中的数据赋值给data变量
    case channel3 <- data:
        // 将data写入channel3
    default:
        // 当没有任何通道操作时执行default语句
}

  select语句中可以包含多个case子句,每个case子句表示一个通道操作。<-符号用于从通道中读取数据,channel <- data用于将数据写入通道。 select语句的执行流程为:

  • 如果有多个通道都可以操作,则随机选择一个进行操作。
  • 如果没有任何通道可以操作,则会执行default语句(如果有)。
  • 如果没有default语句,则select语句会阻塞,直到至少有一个通道可以操作。

  下面是一个使用select语句的示例:

package main
import (
    "fmt"
    "time"
)
func main() {
    ch1 := make(chan int)
    ch2 := make(chan int)
    go func() {
        time.Sleep(time.Second)
        ch1 <- 1
        fmt.Println("ch1 ending")
    }()
    go func() {
        time.Sleep(2 * time.Second)
        ch2 <- 2
        fmt.Println("ch2 ending")
    }()
    select {
        case data := <-ch1:
            fmt.Println("收到ch1的数据:", data)
        case data := <-ch2:
            fmt.Println("收到ch2的数据:", data)
        case <-time.After(100 * time.Second):
            fmt.Println("超时:没有接收到任何数据")
    }
}

  在上面的例子中,我们创建了两个通道ch1ch2,并分别在不同的goroutine中向它们发送数据。然后使用select语句监听这两个通道的操作,当其中一个通道可用时,就会执行对应的case语句。

  在这个例子中,由于ch1的数据发送操作会在1秒后执行,而ch2的数据发送操作会在2秒后执行,因此select语句会等待1秒后,执行ch1case语句,输出"收到ch1的数据: 1"。如果我们将ch1的发送操作改为在2秒后执行,那么select语句将会等待2秒后,执行ch2case语句,输出"收到ch2的数据: 2"。

  需要注意的是,select语句的执行顺序是随机的,所以不能依赖于某个通道的操作先于其他通道。这也是使用select语句时需要注意的地方之一。

  如果希望持续监听多个通道的操作,可以将select语句放在一个无限循环中。

package main
import (
    "fmt"
    "time"
)
func main() {
    channel1 := make(chan int)
    channel2 := make(chan string)
    go func() {
        for i := 0; i < 5; i++ {
            time.Sleep(time.Second)
            channel1 <- i
        }
        close(channel1)
    }()
    go func() {
        for i := 0; i < 5; i++ {
            time.Sleep(time.Second)
            channel2 <- fmt.Sprintf("Message %d", i)
        }
        close(channel2)
    }()
    for {
        select {
        case data1, ok := <-channel1:
            if ok {
                fmt.Println("Received from channel1:", data1)
            } else {
                fmt.Println("Channel1 closed")
                channel1 = nil
            }
        case data2, ok := <-channel2:
            if ok {
                fmt.Println("Received from channel2:", data2)
            } else {
                fmt.Println("Channel2 closed")
                channel2 = nil
            }
        }
        if channel1 == nil && channel2 == nil {
            break
        }
    }
    fmt.Println("Done")
}

  在这个示例中,创建了两个通道channel1channel2,分别用于发送不同类型的数据。然后分别启动两个goroutine,每个goroutine向对应的通道发送一些数据,然后关闭通道。其运行得结果如图:

 

             

  上述代码中 ok 是从通道的属性中获取的。在Go语言中,当从通道接收数据时,会返回两个值:接收到的数据和一个表示通道是否已关闭的布尔值。这个布尔值就是ok。 当通道已关闭且没有数据可读取时,会返回通道元素类型的零值和false。当通道还未关闭且有数据可读取时,会返回通道中的数据和true 因此,使用data, ok := <-channel的语法可以同时接收通道中的数据和判断通道是否已关闭。data表示接收到的数据,ok表示通道是否还有数据可读取。如果okfalse,则表示通道已关闭,没有数据可读取。

  在主函数中,我们使用无限循环和select语句来持续监听这两个通道的操作。每次循环时,select语句会选择其中一个可用的通道进行操作。如果通道关闭,我们会将对应的通道设置为nil,以便在后续的循环中跳过该通道的操作。当两个通道都关闭,即channel1channel2都为nil时,我们跳出循环,程序结束。

  运行上述代码,你会看到程序持续监听两个通道的操作,并打印接收到的数据,直到两个通道都关闭。最后,程序输出"Done"并结束。

  

 

 

 

标签: GO

目录
相关文章
|
供应链 Go
掌握Go语言:利用Go语言的单向通道和select语句,提升库存管理效率(21)
掌握Go语言:利用Go语言的单向通道和select语句,提升库存管理效率(21)
175 0
|
程序员 Go
Golang深入浅出之-Select语句在Go并发编程中的应用
【4月更文挑战第23天】Go语言中的`select`语句是并发编程的关键,用于协调多个通道的读写。它会阻塞直到某个通道操作可行,执行对应的代码块。常见问题包括忘记初始化通道、死锁和忽视`default`分支。要解决这些问题,需确保通道初始化、避免死锁并添加`default`分支以处理无数据可用的情况。理解并妥善处理这些问题能帮助编写更高效、健壮的并发程序。结合使用`context.Context`和定时器等工具,可提升`select`的灵活性和可控性。
297 2
|
7月前
|
人工智能 监控 Kubernetes
Go语言在select语句中实现优先级
Go语言中的`select`语句用于监控多个Channel的发送或接收操作,选择就绪的分支执行。它支持多种使用场景,如空`select`永久阻塞、单`case`阻塞读写、多`case`随机选择、配合`default`实现非阻塞操作等。通过嵌套`select`还可实现执行优先级,适用于如Kubernetes中任务调度等实际场景。
|
7月前
|
Go
理解 Go 语言中的 select 用法
本文深入解析了Go语言中`select`的用法,它类似于`switch case`,但仅用于通道(channel)的操作。文章通过多个示例说明了`select`的基本用法、避免死锁的方法、随机性特点以及如何实现超时机制。同时总结了`select`与`switch`的区别:`select`专用于通道操作,case执行是随机的,需注意死锁问题,且不支持`fallthrough`和函数表达式。
317 1
理解 Go 语言中的 select 用法
|
5月前
|
Go 开发者
Go语言实战案例:使用select监听多个channel
本文为《Go语言100个实战案例 · 网络与并发篇》第5篇,详解Go并发核心工具`select`的使用。通过实际案例讲解如何监听多个Channel、实现多任务处理、超时控制和非阻塞通信,帮助开发者掌握Go并发编程中的多路异步事件处理技巧。
|
7月前
|
监控 Go 开发者
深入解析 go 语言中的 select 语句
在 Go 语言中,`select` 是专为并发编程设计的控制结构,用于在多个 channel 操作间进行非阻塞选择。它类似于 `switch`,但所有 case 分支必须是 channel 的 I/O 操作。本文通过通俗易懂的语言和丰富代码示例,详细讲解 `select` 的各种用法,包括基本语法、空 `select`、多分支选择、`default` 分支、特点总结及最佳实践,适合初学者和有经验的开发者学习参考。掌握 `select`,能有效提升 Go 并发编程的灵活性与效率。
269 6
|
7月前
|
Go 调度 开发者
Go 并发编程基础:select 多路复用
Go 语言中的 `select` 是一种强大的并发控制结构,用于同时监听多个通道操作。它支持随机选择就绪的通道、阻塞等待以及通过 `default` 实现非阻塞通信。结合 `time.After()`,可轻松实现超时机制,适用于网络请求、任务调度等场景。本文详细介绍了 `select` 的基本用法、特性及实战技巧,如合并多通道输入、处理通道关闭等,帮助开发者高效管理协程与通道交互,避免常见陷阱。
|
存储 Go 索引
GO 集合 map 使用总结
GO 集合 map 使用总结
295 1
|
Go
Go并发编程:玩转select语句
Go并发编程:玩转select语句
158 0
Go并发编程:玩转select语句

热门文章

最新文章