概述

golang channel 是我们常用的一个用于处理协程通信的最重要的工具, 在一些边界情况下的表现,差异化很大。

本文就golang在channel正常状态、关闭状态、nil 状态下的发送接收以及关闭的表现做一个简单的测试说明, 有任何疑问欢迎交流探讨。

channel在各种状态下的操作表现结论

通道操作正常状态关闭状态nil
发送X (panic: send on closed channel)X
接收√ (接收到的为初始值)X
关闭X (panic: close of closed channel)X

正常发送和接收

示例代码

package main

import (
	"fmt"
)
func main() {
	ch := make(chan string)
	go send(ch)
	recv(ch)
	close(ch)       // 关闭
}
// 接收
func recv(ch <-chan string) {
	x := <-ch
	fmt.Println("result:", x)
}
// 发送
func send(ch chan<- string) {
	ch <- "send_val"
}

复制代码

运行结果: (一切表现正常)

result: send_val
复制代码

关闭状态的channel进行操作

package main

import (
	"fmt"
	"time"
)

func main() {
	ch := make(chan string)
	close(ch)   // ok
	close(ch)   // panic: close of closed channel
	go send(ch) // panic: send on closed channel
	recv(ch)    // result:
	time.Sleep(time.Second)
}

func send(ch chan<- string) {
	ch <- "send_val"
}

func recv(ch <-chan string) {
	x := <-ch
	fmt.Println("result:", x)
}
复制代码
nil
fatal error: all goroutines are asleep - deadlock!panic: close of nil channelfatal error: all goroutines are asleep - deadlock!
nilgoroutine 1 [chan receive (nil chan)]:
package main

import (
	"fmt"
	"time"
)

func main() {
	var ch chan string
	close(ch)   // panic: close of nil channel
	go recv(ch) //   goroutine 1 [chan receive (nil chan)]:
	send(ch)    // fatal error: all goroutines are asleep - deadlock!
	time.Sleep(time.Second)
}

func send(ch chan<- string) {
	ch <- "send_val"
}

func recv(ch <-chan string) {
	x := <-ch
	fmt.Println("result:", x)
}
复制代码