golang中select语句的简单实例

目录
  • 前言
  • 1.先举个简单例子
  • 2. 避免造成死锁
  • 3. select 随机性
  • 4. select 的超时
  • 5. 读取/写入都可以
  • 6. 总结一下

前言

在golang语言中,select语句 就是用来监听和channel有关的IO操作,当IO操作发生时,触发相应的case动作。有了 select语句,可以实现 main主线程 与 goroutine线程 之间的互动。

select {
    case <-ch1 :     // 检测有没有数据可读
        // 一旦成功读取到数据,则进行该case处理语句
    case ch2 <- 1 :  // 检测有没有数据可写
        // 一旦成功向ch2写入数据,则进行该case处理语句
    default:
        // 如果以上都没有符合条件,那么进入default处理流程
}

注意事项:

  • select语句 只能用于channel信道的IO操作,每个case都必须是一个信道。
  • 如果不设置 default条件,当没有IO操作发生时,select语句就会一直阻塞;
  • 如果有一个或多个IO操作发生时,Go运行时会随机选择一个case执行,但此时将无法保证执行顺序;
  • 对于case语句,如果存在信道值为nil的读写操作,则该分支将被忽略,可以理解为相当于从select语句中删除了这个case;
  • 对于空的 select语句,会引起死锁;
  • 对于在 for中的select语句,不能添加 default,否则会引起cpu占用过高的问题;

1.先举个简单例子

先创建两个信道,并在 select 前往 c2 发送数据

package main

import (
	"fmt"
)

//go的通道选择器 让你可以同时等待多个通道操作。go协程和通道以及选择器的结合是go的一个强大特性。

func main() {
	// 在我们的例子中,我们将从两个通道中选择。
	c1 := make(chan string, 1)
	c2 := make(chan string, 1)

	c2 <- "nihao"

	//go func() {
	//	time.Sleep(time.Second * 1)
	//	c1 <- "one"
	//}()
	//
	//go func() {
	//	time.Sleep(time.Second * 2)
	//	c2 <- "two"
	//}()

	//我们使用 `select` 关键字来同时等待这两个值,并打印各自接收到的值。
	//for i := 0; i < 2; i++ {
	select {
	case msg1 := <-c1:
		fmt.Println("received", msg1)
	case msg2 := <-c2:
		fmt.Println("received", msg2)
	default:
		fmt.Println("No data received")
	}
	//}

}

在运行 select 时,会遍历所有(如果有机会的话)的 case 表达式,只要有一个信道有接收到数据,那么 select 就结束,所以输出如下

2. 避免造成死锁

select 在执行过程中,必须命中其中的某一分支。

如果在遍历完所有的 case 后,若没有命中(命中:也许这样描述不太准确,我本意是想说可以执行信道的操作语句)任何一个 case 表达式,就会进入 default 里的代码分支。

package main

import (
	"fmt"
)

//go的通道选择器 让你可以同时等待多个通道操作。go协程和通道以及选择器的结合是go的一个强大特性。

func main() {
	// 在我们的例子中,我们将从两个通道中选择。
	c1 := make(chan string, 1)
	c2 := make(chan string, 1)

	//c2 <- "nihao"

	//go func() {
	//	time.Sleep(time.Second * 1)
	//	c1 <- "one"
	//}()
	//
	//go func() {
	//	time.Sleep(time.Second * 2)
	//	c2 <- "two"
	//}()

	//我们使用 `select` 关键字来同时等待这两个值,并打印各自接收到的值。
	//for i := 0; i < 2; i++ {
	select {
	case msg1 := <-c1:
		fmt.Println("received", msg1)
	case msg2 := <-c2:
		fmt.Println("received", msg2)
		//default:
		//	fmt.Println("No data received")
		//}
	}
}

但如果你没有写 default 分支,select 就会阻塞,直到有某个 case 可以命中,而如果一直没有命中,select 就会抛出 deadlock 的错误,就像下面这样子。

1.解决这个问题的方法有两种

一个是,养成好习惯,在 select 的时候,也写好 default 分支代码,尽管你 default 下没有写任何代码。

另一个是,让其中某一个信道可以接收到数据

3. select 随机性

之前学过 switch 的时候,知道了 switch 里的 case 是顺序执行的,但在 select 里却不是。

通过下面这个例子的执行结果就可以看出

4. select 的超时

当 case 里的信道始终没有接收到数据时,而且也没有 default 语句时,select 整体就会阻塞,但是有时我们并不希望 select 一直阻塞下去,这时候就可以手动设置一个超时时间。

5. 读取/写入都可以

上面例子里的 case,好像都只从信道中读取数据,但实际上,select 里的 case 表达式只要求你是对信道的操作即可,不管你是往信道写入数据,还是从信道读出数据。

6. 总结一下

select 与 switch 原理很相似,但它的使用场景更特殊,学习了本篇文章,你需要知道如下几点区别:

  1. select 只能用于 channel 的操作(写入/读出),而 switch 则更通用一些;
  2. select 的 case 是随机的,而 switch 里的 case 是顺序执行;
  3. select 要注意避免出现死锁,同时也可以自行实现超时机制;
  4. select 里没有类似 switch 里的 fallthrough 的用法;
  5. select 不能像 switch 一样接函数或其他表达式。

到此这篇关于golang中select语句的文章就介绍到这了,更多相关go中select语句内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • golang中的select关键字用法总结

    1.官方解释 一个select语句用来选择哪个case中的发送或接收操作可以被立即执行.它类似于switch语句,但是它的case涉及到channel有关的I/O操作.即select就是用来监听和channel有关的IO操作,当 IO 操作发生时,触发相应的动作. 2.要点 如果有一个或多个IO操作可以完成,则Go运行时系统会随机的选择一个执行,否则的话,如果有default分支,则执行default分支语句,如果连default都没有,则select语句会一直阻塞,直到至少有一个IO操作可以进

  • Golang中switch语句和select语句的用法教程

    本文主要给大家介绍了关于Golang中switch和select用法的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍: 一.switch语句 switch语句提供了一个多分支条件执行的方法.每一个case可以携带一个表达式或一个类型说明符.前者又可被简称为case表达式.因此,Go语言的switch语句又分为表达式switch语句和类型switch语句. 1.表达式switch语句 var name string ... switch name { case "Golang"

  • 简介Go语言中的select语句的用法

    在Go编程语言中的select语句的语法如下: 复制代码 代码如下: select {     case communication clause  :        statement(s);          case communication clause  :        statement(s);     /* you can have any number of case statements */     default : /* Optional */        stat

  • Go语言中Select语句用法实例

    本文实例讲述了Go语言中Select语句用法.分享给大家供大家参考.具体分析如下: select 语句使得一个 goroutine 在多个通讯操作上等待. select 会阻塞,直到条件分支中的某个可以继续执行,这时就会执行那个条件分支.当多个都准备好的时候,会随机选择一个. 复制代码 代码如下: package main import "fmt" func fibonacci(c, quit chan int) {         x, y := 1, 1         for {

  • golang中select语句的简单实例

    目录 前言 1.先举个简单例子 2. 避免造成死锁 3. select 随机性 4. select 的超时 5. 读取/写入都可以 6. 总结一下 前言 在golang语言中,select语句 就是用来监听和channel有关的IO操作,当IO操作发生时,触发相应的case动作.有了 select语句,可以实现 main主线程 与 goroutine线程 之间的互动. select { case <-ch1 : // 检测有没有数据可读 // 一旦成功读取到数据,则进行该case处理语句 cas

  • 10个mysql中select语句的简单用法

    1.select语句可以用回车分隔 $sql="select * from article where id=1" 和 $sql="select * from article where id=1",都可以得到正确的结果,但有时分开写或许能更明了一点,特别是当sql语句比较长时 2.批量查询数据 可以用in来实现 $sql="select * from article where id in(1,3,5)" 3.使用concat连接查询的结果 $

  • 深入浅出Golang中select的实现原理

    目录 概述 select实现原理 执行流程 case数据结构 执行select 循环 总结 概述 在go语言中,select语句就是用来监听和channel有关的IO操作,当IO操作发生时,触发相应的case操作,有了select语句,可以实现main主线程与goroutine线程之间的互动.需要的朋友可以参考以下内容,希望对大家有帮助. select实现原理 Golang实现select时,定义了一个数据结构表示每个case语句(包含default,default实际上是一种特殊的case),

  • 一文带你了解Golang中select的实现原理

    目录 概述 结构 现象 非阻塞的收发 随机执行 编译 直接阻塞 独立情况 非阻塞操作 通用情况 运行时 初始化 循环 总结 概述 select是go提供的一种跟并发相关的语法,非常有用.本文将介绍 Go 语言中的 select 的实现原理,包括 select 的结构和常见问题.编译期间的多种优化以及运行时的执行过程. select 是一种与 switch 非常相似的控制结构,与 switch 不同的是,select 中虽然也有多个 case,但是这些 case 中的表达式都必须与 Channel

  • ASP.NET中Web API的简单实例

    一.Web API的路由 1.在Visual Studio中新建MVC4项目,在App_Start目录下有一个WebApiConfig.cs文件,这个文件中就是相应的Web API的路由配置了. 2.Web API 框架默认是基于 Restful 架构模式的,与ASP.NET MVC 有区别的是,它会根据 Http 请求的 HttpMethod(Get.Post.Put.Delete)来在Controller 中查找 Action,规则是:Action 名中是否以Get.Post 开头?Acti

  • MySQL中select语句使用order按行排序

    本文介绍MySQL数据库中执行select查询语句,并对查询的结果使用order by 子句进行排序. 再来回顾一下SQL语句中的select语句的语法: Select 语句的基本语法: Select <列的集合> from <表名> where <条件> order by <排序字段和方式> 如果要对查询结果按某个字段排序,则要使用order by 子句,如下: select * from <表名> order by <字段名称>

  • java从字符串中提取数字的简单实例

    随便给你一个含有数字的字符串,比如: String s="eert343dfg56756dtry66fggg89dfgf"; 那我们如何把其中的数字提取出来呢?大致有以下几种方法,正则表达式,集合类,还有就是String类提供的方法. 1 String类提供的方法: package 测试练习; import Java.util.*; public class get_StringNum { /** *2016.10.25 */ public static void main(Strin

  • PHP 在数组中搜索给定的简单实例 array_search 函数

    array_search() PHP array_search() 函数用于在数组中搜索给定的值,如果成功则返回相应的键名,否则返回 FALSE . 语法: mixed array_search( mixed needle, array array [, bool strict] )参数说明: 参数 说明 needle 需要在数组中搜索的值,如果是字符串,则区分大小写 array 需要检索的数组 strict 可选,如果设置为 TRUE ,则还会对 needle 与 array 中的值类型进行检

  • 模拟javascript中的sort排序(简单实例)

    一.javascript中sort对数据进行排序的原理 sort() 方法对数组的元素做原地的排序,并返回这个数组. sort 可能不是稳定的.默认按照字符串的Unicode码位点排序; 语法:arr.sort([compareFunction]) 参数 compareFunction 可选.用来指定按某种顺序进行排列的函数.如果省略,元素按照转换为的字符串的诸个字符的Unicode位点进行排序. 如果 compareFunction(a, b) 小于 0 ,那么 a 会被排列到 b 之前: 如

  • js动态添加的DIV中的onclick事件简单实例

    最简单的是这样: <input type="button" onclick="alert(this.value)" value="我是 button" /> 动态添加onclick事件: <input type="button" value="我是 button" id="bu"> <script type="text/javascript&quo

随机推荐