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
*/
}