文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

golang中select语句的简单实例

2024-04-02 19:55

关注

前言

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

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

注意事项:

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语句内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯