go 常见面试题

一、如何判断channel是否已经关闭?

用 select 和 <-ch 来结合可以解决这个问题
ok的结果和含义:
true:读到数据,并且通道没有关闭。
false:通道关闭,无数据读到。

ch := make(chan int, 10)
	go func() {
		for i:=1;i<10;i++{
			ch <- i
		}
	}()
	time.Sleep(1*time.Second)
	close(ch)
	for i:=0;i<10;i++{
		select {
		case v, ok := <- ch:
			if ok {
				fmt.Println(v)
			}else{
				fmt.Println("关掉了")
			}
		default:
			fmt.Println("没啥事")
	}
}

需要注意:
1.case 的代码必须是 _, ok:= <- ch 的形式,如果仅仅是 <- ch 来判断,是错的逻辑,因为主要通过 ok的值来判断;
2.select 必须要有 default 分支,否则会阻塞函数,我们要保证一定能正常返回;

官方推荐通过 context 来配合使用,我们可以通过一个 ctx 变量来指明 close 事件,而不是直接去判断 channel 的一个状态

select {
case <-ctx.Done():
    // ... exit
    return
case v, ok := <-c:
    // do something....
default:
    // do default ....
}

二、golang 对已经关闭的的chan进行读写,会怎么样?

1、写已经关闭的channel

package main
 
func main(){
	c:= make(chan int,2)
	close(c)
	c <- 1
}

运行结果:
在这里插入图片描述

会发生panic

2、读已经关闭的channel

package main
 
import (
	"fmt"
)
func main(){
	c:= make(chan int,2)	
	c <- 1
	close(c)
	num,ok :=<-c
	fmt.Println(num,ok)
	num,ok =<-c
	fmt.Println(num,ok)
	num,ok =<-c
	fmt.Println(num,ok)
}

运行结果:
在这里插入图片描述

  1. 读已经关闭的 chan 能一直读到东西,但是读到的内容根据通道内关闭前是否有元素而不同。
  2. 如果 chan 关闭前,buffer 内有元素还未读 , 会正确读到 chan 内的值,且返回的第二个 bool 值(是否读成功)为 true。
  3. 如果 chan 关闭前,buffer 内有元素已经被读完,chan 内无值,接下来所有接收的值都会非阻塞直接返回,返回 channel 元素的零值(如果是string就返回空字符串),但是第二个 bool 值一直为 false。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值