我是靠谱客的博主 老实吐司,最近开发中收集的这篇文章主要介绍go channel close之后读写的问题go channel close之后读写的问题,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

go channel close之后读写的问题

  • go channel close之后读写的问题
    • 代码演示
      • 无缓冲读写
      • 有缓存读写
      • 优雅的range
    • 解释
    • 补充:如何限制channel的读写

go channel close之后读写的问题

代码演示

无缓冲读写

package main

import "fmt"

func main() {
	Test1()
}
func Test1() {
	ch := make(chan int)
	close(ch)
	for i := 0; i < 5; i++ {
		fmt.Println(<-ch)
	}
	ch <- 1
}
0
0
0
0
0
panic: send on closed channel

goroutine 1 [running]:
main.Test1()
	C:/Users/68725/Desktop/leetcode/main.go:14 +0xb7
main.main()
	C:/Users/68725/Desktop/leetcode/main.go:6 +0x17

进程 已完成,退出代码为 2

有缓存读写

package main

import "fmt"

func main() {
	Test2()
}
func Test2() {
	ch := make(chan int, 1)
	ch <- 1
	close(ch)
	for i := 0; i < 5; i++ {
		v, ok := <-ch
		if ok {
			fmt.Println("成功读,value=", v)
		} else {
			fmt.Println("channal关闭,值为类型零值")
		}
	}
}
成功读,value= 1
channal关闭,值为类型零值
channal关闭,值为类型零值
channal关闭,值为类型零值
channal关闭,值为类型零值

进程 已完成,退出代码为 0

优雅的range

package main

import "fmt"

func main() {
	Test3()
}
func Test3() {
	ch := make(chan int, 1)
	ch <- 1
	close(ch)
	for v := range ch {
		fmt.Println(v)
	}
	fmt.Println("退出range了")
}

1
退出range了

进程 已完成,退出代码为 0

解释

对于已经close的channel来说,可读不可写,一写就panic。
而读呢,如果channel还有数据,那么先读数据,如果channel里面已经没有数据了,还去读channel,那么此时读出来的是类型零值,对于v, ok := <-ch这种双返回值的ok来说,ok被赋值为false。
如何优雅的读呢?用range,range会自动赋值,并且在关闭channel后自动退出,这样就无需v, ok := <-ch | if ok...这种形式了

补充:如何限制channel的读写

package main

func main() {
	ch := make(chan int, 1)
	ReadCh(ch)
	WriteCh(ch)
}
func ReadCh(ch <-chan int) {
	<-ch
}
func WriteCh(ch chan<- int) {
	ch <- 1
}

在ReadCh函数中,把形参限制为只读,在WriteCh函数中,把形参限制为只写,那么代码就只能在ReadCh中写<- ch语句,如果写ch<-就会报错在这里插入图片描述
WriteCh同理

最后

以上就是老实吐司为你收集整理的go channel close之后读写的问题go channel close之后读写的问题的全部内容,希望文章能够帮你解决go channel close之后读写的问题go channel close之后读写的问题所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(48)

评论列表共有 0 条评论

立即
投稿
返回
顶部