Golang Go语言中Channel学习的一个疑问,请大佬指教

发布于 1周前 作者 yibo5220 来自 Go语言

Golang Go语言中Channel学习的一个疑问,请大佬指教


func main() {
boolChannel()
}

func boolChannel() { ch1 := make(chan int) ch2 := make(chan bool)

go func() {
	for i:=0;i<5;i++ {
		ch1 <- i
	}
	ch2 <- true	//标识位写入 true
}()

go func() {
	for x:= range ch1{
		fmt.Println(x)
	}
}()

<-ch2 //阻塞标识位

}

为什么这个输出结果一会是 0,1,2,3,一会是 0,1,2,3,4

按道理来说,我在主进程一直阻塞了,应该等 goroutine 全部打印完才对呀,百思不得其解


更多关于Golang Go语言中Channel学习的一个疑问,请大佬指教的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

17 回复

应该是 fmt.Println(x)这里的耗时吧,ch1 <- 4 完了之后马上 ch2 <- true,主协程一直阻塞后马上执行<-ch2,这时候 fmt.Println(4)这里卡在主协程结束前后,所以会有不稳定的情况
我的理解是这样

更多关于Golang Go语言中Channel学习的一个疑问,请大佬指教的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这不是很正常啊 打印的 goroutine 你有没有同步机制 去保证 先于 main goroutine 结束 ?

去看看 GMP 的调度把

ch2 <- true 上面加一行 time.Sleep(1 * time.Second)

<-ch2 接受到值,就往后执行了,这时候第二个 goroutine 可能还没执行完成

删掉 ch2 <- true 就可以了

打印完后再往 ch2 写值

加入 wait group 或者 context,不能保证你的 print 在 main 之前

这两个 go 出去的 func 并没有形成锁,只有第一个 func 和 boolChannel 形成了锁,所以你能确保的是全部写入后才会终结 boolChannel 的执行,但 fmt.Println(x)一定执行吗?不一定,因为可能正准备 fmt.Println(x),这个 goroutine 就被切到等待队列里了

(我不知道应不应该使用锁这个名词,基础忘掉了大半,欢迎拍砖)

第一个 go 协程结束时关闭信道
第二个协程直接在主线程执行。

ch2 可以去掉。

ch2 <- true 改成 close(ch1)

ch2 <- true 移到第二个 for 后面

4 进入 ch1 后,true 进入 ch2,
情况 1:主程序先得到 ch2,第二个 func 还没来得及得到 ch1 或者没来得及打印, 程序就退出 输出 0,1,2,3
情况 2:第二个 func 得到 ch1 并且打印,主程序还没来得及得到 ch2,输出 0,1,2,3,4

ch2 <- true //标识位写入 true
这句放到第二个 func 后面就行了

通俗易懂理解了,其实就是想看看不通过 waitGroup 能不能解决,多谢~

可以的,按照云风大侠的说法,通道是最佳解决方案

一般是发送 goroutine 是 close 发送的 chan,接收 goroutine 是关闭阻塞 chan
这样的好处是不会造成 goroutine 泄露,发送完 close,接收 for chan 还是可以接收完数据的,会自己退出,这时候 close 或者发送信号到退出 chan 。

在Go语言中,Channel是用于在不同的goroutine之间进行通信的重要机制。关于你在学习Channel时遇到的疑问,我可以提供以下几点指导:

  1. Channel的基本概念:Channel是一种类型安全的管道,允许你在goroutine之间发送和接收数据。它确保了数据发送和接收的同步性,避免了数据竞争和死锁等问题。

  2. Channel的创建与操作:你可以使用make函数来创建一个Channel,例如ch := make(chan int)。发送数据到Channel使用<-操作符,如ch <- 42;从Channel接收数据也使用<-操作符,如value := <-ch

  3. Channel的阻塞特性:发送数据到无缓冲Channel时,如果接收方未准备好接收,发送操作将阻塞;同样,从无缓冲Channel接收数据时,如果发送方未发送数据,接收操作也会阻塞。有缓冲Channel则根据缓冲区的情况决定是否阻塞。

  4. 关闭Channel:使用close(ch)可以关闭一个Channel,表示没有更多的值会被发送到Channel。接收方可以通过检测语法v, ok := <-ch来判断Channel是否已关闭。

  5. 选择语句(select):在多个Channel上进行操作时,可以使用select语句来等待多个Channel的通信操作。

如果你有更具体的疑问或遇到了特定的代码问题,请提供更详细的描述,这样我可以给出更针对性的解答。希望这些信息对你有所帮助!

回到顶部