首页 > 其他分享 >golang中for select时,如果channel关闭会怎么样?

golang中for select时,如果channel关闭会怎么样?

时间:2023-06-06 16:48:19浏览次数:33  
标签:case ok golang select 关闭 time channel

首先,如果对于一个已经关闭的channel来说,如果此时channel里还有值,则会正确读到channel里的值,且返回的第二个bool值为true;如果关闭前,channel里的值已经被读完,则最后返回的则是channel的零值;

那么针对该问题,我们通过代码来验证一下:

package main

import (
	"fmt"
	"time"
)

const timestamp = "2006-01-02 15:04:05"

func main() {
	chan1 := make(chan int)
	go func() {
		time.Sleep(1 * time.Second)
		chan1 <- 10
		close(chan1)
	}()

	for {
		select {
		case x, ok := <-chan1:
			fmt.Printf("%v,通道读取到:x=%v,ok=%v\n", time.Now().Format(timestamp), x, ok)
			time.Sleep(500 * time.Millisecond)
		default:
			fmt.Printf("%v,通道未读取到,进入到default\n", time.Now().Format(timestamp))
			time.Sleep(500 * time.Millisecond)
		}
	}
}

从结果中看出,我们可以继续读到channel里的值,但是读完之后,却依旧会继续执行读操作,这时候,可通过第二个参数bool值去解决该问题

for {
		select {
		case x, ok := <-chan1:
			fmt.Printf("%v,通道读取到:x=%v,ok=%v\n", time.Now().Format(timestamp), x, ok)
			time.Sleep(500 * time.Millisecond)
			if !ok {
				chan1 = nil
			}
		default:
			fmt.Printf("%v,通道未读取到,进入到default\n", time.Now().Format(timestamp))
			time.Sleep(500 * time.Millisecond)
		}
	}

从输出结果上看,该方法解决了该问题,因为将channel置为nil,在从channel去读数据的话,相当于操作一个为初始化的channel,会一直阻塞。

并且如果select里只有一个已经关闭的case的话,则会一直出现死循环的状态

for {
		select {
		case x, ok := <-chan1:
			fmt.Printf("%v,通道读取到:x=%v,ok=%v\n", time.Now().Format(timestamp), x, ok)
			time.Sleep(500 * time.Millisecond)
			// if !ok {
			// 	chan1 = nil
			// }
			// default:
			// 	fmt.Printf("%v,通道未读取到,进入到default\n", time.Now().Format(timestamp))
			// 	time.Sleep(500 * time.Millisecond)
		}
	}

那么针对上述场景,如果将其置为nil,又会怎么样呢?


	for {
		select {
		case x, ok := <-chan1:
			fmt.Printf("%v,通道读取到:x=%v,ok=%v\n", time.Now().Format(timestamp), x, ok)
			time.Sleep(500 * time.Millisecond)
			if !ok {
				chan1 = nil
			}
			// default:
			// 	fmt.Printf("%v,通道未读取到,进入到default\n", time.Now().Format(timestamp))
			// 	time.Sleep(500 * time.Millisecond)
		}
		fmt.Println("the others information")
	}

从输出结果上看,会panic,引发deadlocl问题,所以,select中最好放入一个default,来避免此类情况发生!

标签:case,ok,golang,select,关闭,time,channel
From: https://www.cnblogs.com/99kol/p/17460946.html

相关文章

  • golang之context
    Golang之Context:提升代码性能的关键在当今数字化世界中,高效的编程语言对于开发人员来说至关重要。Golang作为一种现代化且强大的编程语言,已经在业界迅速崛起,并受到了广泛的关注和采用。Golang以其简洁、高效和并发性能出色而闻名,但是在开发大规模应用时,开发人员必须了解如何优化代......
  • 20个Golang片段让我不再健忘 | 京东云技术团队
    前言本文使用代码片段的形式来解释在 go 语言开发中经常遇到的小功能点,由于本人主要使用 java 开发,因此会与其作比较,希望对大家有所帮助。1.helloworld新手村的第一课,毋庸置疑。packagemainimport"fmt"funcmain(){ fmt.Printf("helloworld")}2.隐形初始化package......
  • DataTemplateSelector介绍
    DataTemplateSelector可以帮助我们实现动态选择数据绑定的模版,如通过ListView+DataTemplateSelector实现微信朋友圈或聊天列表效果。Github已有聊天效果图  喜欢阅读代码请直接移步:https://github.com/nishanil/Xamarin.Forms-Samples/tree/master/DataTemplateSelector本文通过......
  • Golang高性能编程--slice的学习总结
    在go语言中,数组变量属于值类型,因此当一个数组变量被复制或者传递时,实际上会复制整个数组。eg,将a赋值给b,修改a中的元素,并不会修改b中的元素。为了避免复制数组,一般会传递指向数组的指针。packagemainimport"fmt"funcmain(){ a:=[...]int{1,2,3} b:=a a[0]=100......
  • 使用Go语言中的Channel实现并发编程
    引言:Go语言是一门开源的编程语言,以其高效、简洁和并发编程的能力而闻名。在Go语言中,Channel是一个重要的概念,它提供了一种安全、高效地在并发程序中进行通信的机制。本文将介绍Go语言中的Channel,以及如何使用Channel实现并发编程。一、什么是Channel?在Go语言中,Channel是一种用......
  • 算法 in Golang:D & C(分而治之)
    算法inGolang:D&C(分而治之)D&C算法(策略)Divide&Conquer属于递归算法的一种其实它更像是一种思路、策略递归递归Recursion基线条件BaseCase递归条件RecursiveCaseD&C的步骤找到一个简单的基线条件(BaseCase)把问题分开处理,直到它变为基线条件例......
  • Linux下三组I/O复用函数的比较(select、poll、epoll)
        前面我们讨论了select、poll和epoll三组I/O复用系统调用,这三组系统调用都能同时监听多个文件描述符。它们将等待由timeout参数指定的超时时间,直到一个或多个文件描述符上有事件发生时返回,返回值是就绪的文件描述符的数量。返回0表示没有事件发生。现在我们从事件集、最......
  • Golang Web--中间件的学习总结
    关于在golang中的中间件,可以翻阅笔者之前的博客,在这里不予详细说明。这里简单介绍下中间件的高级用法:1.如果每个路由分别要配置多个中间价,该如何处理2.如果有多个路由分别要配置多个中间件,该如何处理3.尝试不定义结构体开发中间件packagemainimport("context""......
  • 极客时间--golang并发实战课--Mutex的常见使用错误场景
    1.Lock/Unlock没有成对出现,就意味着会出现死锁的情况,或者是因为Unlock一个未加锁的Mutex而导致panic。2.第二种误用是Copy已使用的Mutex。Packagesync的同步原语在使用后是不能复制的。原因在于,Mutex是一个有状态的对象,它的state字段记录这个锁的状态。如果你要复......
  • 极客时间--golang并发编程实战课--Mutex学习总结
    互斥锁的实现机制互斥锁是并发控制的一个手段,是为了避免竞争而建立的一种并发控制机制。在并发编程中,如果程序中的一部分会被并发访问或修改,那么,为了避免并发访问导致的意想不到的结果,这部分程序需要被保护起来,这部分被保护起来的程序,就叫做临界区。可以说,临界区就是一个被共......