channe状态与读取操作之间的关系

本文深入探讨了Go语言中channel的状态及其与读取操作的关系。详细解释了如何在并发环境中正确处理channel的读取,确保数据同步的安全性和效率。通过实例分析,阐述了满channel与空channel的读取条件,以及阻塞与非阻塞读取的原理。
摘要由CSDN通过智能技术生成

channe状态与读取操作之间的关系


本文主要记录通道不同状态下,读取和写入通道结果之间的关系。
整体上以记录表格形式呈现,后边每一个test()方法表示了一种情况。

操作Channel状态结果
Read未初始化阻塞
Read已初始化且非空有值读取到正确值
Read已初始化但为空所在协程阻塞
Read关闭状态的读取到默认值
Read通道为只写编译错误
Write未初始化所在协程阻塞
Write已初始化且缓冲未满值可以被正确写入
Write已初始化但缓冲已满此协程阻塞,直到有值被取走
write通道为只读编译错误
Close未初始化的channel会引发panic
Close已初始化且缓冲有值通道关闭,并读取到值,最后读取到默认零值
Close已初始化且缓冲无值的channel通道关闭并读取到默认值
Close关闭一个已经关闭的channel会引发panic
Close关闭一个只读的channel会引发panic
Close关闭一个只写的channel通道会正常关闭
package main

import (
	"fmt"
)

func main() {

	test1()  // 1. 读取一个未初始化的channel---->此协程永久阻塞
	test2()  // 2. 读取一个初始化并非空的channel---->正确读到值
	test3()  // 3. 读取一个初始化但为空的channel---->此协程永久阻塞
	test4()  // 4. 读取一个关闭的channel---->默认值,false
	test5()  // 5. 读取一个只写类型的channel---->编译错误
	test6()  // 6. 写入一个未初始化的channel---->此协程永久阻塞
	test7()  // 7. 写入一个初始化且满缓冲的channel---->此协程阻塞,直到有值被取走
	test8()  // 8. 写入一个初始化且缓冲未满的channel---->值可以正常写入
	test9()  // 9. 写入一个关闭的channel---->会引发panic
	test10() // 10. 写入一个只读channel---->编译错误
	test11() // 11. 关闭一个未初始化的channel---->会引发panic
	test12() // 12. 关闭一个初始化且缓冲有值的channel---->通道关闭,且读取到缓冲中的值,直到无值了才读取到默认值
	test13() // 13. 关闭一个初始化且缓冲无值的channel---->通道关闭,读取到的值为默认值。
	test14() // 14. 关闭一个已经关闭了的channle---->会引发panic
	test15() // 15. 关闭一个只读的channel---->会引发panic
	test16() // 16. 关闭一个只写的channel---->正常关闭

}

// 1. 读取一个未初始化的channel---->此协程永久阻塞
func test1() {
	var streamChannel chan int
	fmt.Println("streamChannel is ", streamChannel)
	fmt.Printf("read channel: %v", <-streamChannel)

	/*

	streamChannel is  <nil>
	fatal error: all goroutines are asleep - deadlock!

	*/
}

// 2. 读取一个初始化并非空的channel---->正确读到值
func test2() {
	var streamChannel = make(chan int, 1)
	fmt.Println("streamChannel is ", streamChannel)
	streamChannel <- 2
	fmt.Printf("read channel: %v", <-streamChannel)

	/*

	streamChannel is  0xc000034070
	read channel: 2

	*/
}

// 3. 读取一个初始化但为空的channel---->此协程永久阻塞
func test3() {
	var streamChannel = make(chan int, 1)
	fmt.Println("streamChannel is ", streamChannel)
	fmt.Printf("read channel: %v", <-streamChannel)
	/*

	streamChannel is  0xc000082000
	fatal error: all goroutines are asleep - deadlock!

	*/

}

// 4. 读取一个关闭的channel---->默认值,false
func test4() {
	var streamChannel = make(chan int, 1)
	close(streamChannel)
	select {
	case value, ok := <-streamChannel:
		fmt.Printf("value:%v  ,  ok: %v", value, ok)
	}

	/*

	value:0  ,  ok: false

	*/

}

// 5. 读取一个只写类型的channel---->编译错误
func test5() {
	//var streamChannel = make(chan <-int,1)
	//var value = <- streamChannel		//直接爆红编译错误
	/*

	invalid operation: <-streamChannel (receive from send-only type chan<- int)

	*/
}

// 6. 写入一个未初始化的channel---->此协程永久阻塞
func test6() {
	var streamChannel chan int
	fmt.Printf("streamChannel is %v\n", streamChannel)
	streamChannel <- 6
	fmt.Printf("write the end!")
	/*

	streamChannel is <nil> 
	fatal error: all goroutines are asleep - deadlock!

	*/
}

// 7. 写入一个初始化且满缓冲的channel---->此协程阻塞,直到有值被取走
func test7() {
	var streamChannel = make(chan int, 2)
	fmt.Printf("streamChannel:%v\n", streamChannel)
	streamChannel <- 7
	streamChannel <- 77
	streamChannel <- 777

	/*

	fatal error: all goroutines are asleep - deadlock!
	streamChannel:0xc000082000
		
	*/
}

// 8. 写入一个初始化且缓冲未满的channel---->值可以正常写入
func test8() {
	var streamChannel = make(chan int, 3)
	fmt.Printf("streamChannel is %v\n", streamChannel)
	streamChannel <- 8
	streamChannel <- 88
	fmt.Printf("write the end!")
	/*

	streamChannel is 0xc000082000
	write the end!
	
	*/
}

// 9. 写入一个关闭的channel---->会引发panic
func test9() {
	var streamChannel = make(chan int, 1)
	fmt.Printf("streamChannel is %v\n", streamChannel)
	close(streamChannel)
	fmt.Printf("streamChannel is %v\n", streamChannel)
	streamChannel <- 9
	fmt.Printf("write the end!")

	/*

	streamChannel is 0xc000082000
	streamChannel is 0xc000082000
	panic: send on closed channel

	*/

}

// 10. 写入一个只读channel---->编译错误
func test10() {

	//var streamChannel = make(<- chan int,1)
	//fmt.Printf("streamChannel is %v",streamChannel)
	//streamChannel <- 10
	//fmt.Printf("write the end!")
	/*

	invalid operation: streamChannel <- 10 (send to receive-only type <-chan int)

	*/
}

// 11. 关闭一个未初始化的channel---->会引发panic
func test11() {
	var streamChannel chan int
	fmt.Printf("streamChannel is %v\n", streamChannel)
	close(streamChannel)
	fmt.Printf("the end!")

	/*

	streamChannel is <nil>
	panic: close of nil channel

	*/
}

// 12. 关闭一个初始化且缓冲有值的channel---->通道关闭,且读取到缓冲中的值,直到无值了才读取到默认值
func test12() {
	var streamChannel = make(chan int, 2)
	fmt.Printf("streamChannel is %v\n", streamChannel)
	streamChannel <- 12
	streamChannel <- 1212
	close(streamChannel)
	fmt.Printf("第一次读取值:%v\n", <-streamChannel)
	fmt.Printf("第二次读取值:%v\n", <-streamChannel)
	fmt.Printf("第三次读取值:%v\n", <-streamChannel) // 前两次读完之后,通道里面没有值了,再次读取时,就是默认值了
	fmt.Printf("read the end!")

	/*

	streamChannel is 0xc000082000
	第一次读取值:12
	第二次读取值:1212
	第三次读取值:0
	read the end!

	*/
}

// 13. 关闭一个初始化且缓冲无值的channel---->通道关闭,读取到的值为默认值。
func test13() {
	var streamChannel = make(chan int, 2)
	close(streamChannel)
	fmt.Printf("streamChannel is %v\n", streamChannel)
	fmt.Printf("第一次读取通道里的值:%v\n", <-streamChannel)
	fmt.Printf("第二次读取通道里的值:%v\n", <-streamChannel)
	fmt.Printf("第三次读取通道里的值:%v\n", <-streamChannel) // 无论读多少次,读到的都是默认值

	/*

	streamChannel is 0xc000034070
	第一次读取通道里的值:0
	第二次读取通道里的值:0
	第三次读取通道里的值:0

	*/

}

// 14. 关闭一个已经关闭了的channle---->会引发panic
func test14() {
	var streamChannel = make(chan int, 1)
	fmt.Printf("1. streamChannel is %v\n", streamChannel)
	close(streamChannel)
	fmt.Printf("2. streamChannel is %v\n", streamChannel)
	close(streamChannel)
	fmt.Printf("3. streamChannel is %v\n", streamChannel) // 可以看到"关闭一个已经关闭了的channel会引发panic"

	/*

	1. streamChannel is 0xc000034070
	2. streamChannel is 0xc000034070
    panic: close of closed channel

	*/

}

// 15. 关闭一个只读的channel---->会引发panic
func test15() {
	//var streamChannel = make(<-chan int, 1)
	//fmt.Printf("streamChannel is %v\n", streamChannel)
	//close(streamChannel)// 直接爆红,不允许编译
}

// 16. 关闭一个只写的channel---->正常关闭
func test16() {
	var streamChannel = make(chan<- int, 1)
	fmt.Printf("streamChannel is %v\n", streamChannel)
	close(streamChannel)
	fmt.Printf("streamChannel is %v\n", streamChannel)
	/*

	streamChannel is 0xc000034070
	streamChannel is 0xc000034070

	*/
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值