go语言中,说到并发先想到的就是goroutine,在go程序中,我们可以执行成千上万个goroutine协程,但是只是单纯的并发执行某个函数意义是不大的,既能够实现在函数与函数之间交换数据,又能使成千上万的函数一起执行,这才是go语言设计的精妙之处。
Go语言的并发模型是CSP(Communicating Sequential Processes),提倡通过通信共享内存而不是通过共享内存而实现通信。
这句话就是channel的核心设计理念。
channel在Go 语言中是一种特殊的类型(引用类型)。channel像一个传送带或者队列,总是遵循先入先出(First In First Out)的规则,保证收发数据的顺序。每一个通道都是一个具体类型的导管,也就是声明channel的时候需要为其指定元素类型。
下面介绍一下channel的用法:
1、创建和声明:
//声明
var ch1 chan int // 声明一个传递整型的通道
var ch2 chan string// 声明一个传递字符串的通道
var ch3 chan []int // 声明一个传递int切片的通道
var ch4 chan map[int]int // 声明一个传递map的通道
// 下面一般用于控制通道的权限才用
// 大多用于函数的入参来作为声明
var ch1 <-chan int // 声明一个只读整型的通道
var ch1 chan<- int // 声明一个只写整型的通道
//创建
ch5 := make(chan int)
ch6 := make(chan int,10) // 10为channel的容量大小,当channel里面有10个元素时候,这时往里面塞会阻塞
ch7 := make(chan string)
ch8 := make(chan []int)
ch9 := make(chan map[int]int )
2、channel的一些基本操作:发送(send)、接收(receive)和关闭(close)三种操作
// 发送和接收都使用 <- 符号。
// 初始化channel
ch := make(chan int)
// 把1发送到ch中
ch <- 1
// 从ch中接收值并赋值给变量x
x := <- ch
// 从ch中接收值,忽略结果
<-ch
// 关闭channel
close(ch)
以下列一下channel中的操作可能的状态:
操作 | nil的channel | 正常channel | 已关闭channel |
<- ch | 阻塞 | 成功或阻塞 | 读到零值 |
ch <- | 阻塞 | 成功或阻塞 | panic |
close(ch) | panic | 成功 | panic |
对于nil通道的情况,也并非完全遵循上表,有1个特殊场景:当nil
的通道在select
的某个case
中时,这个case会阻塞,但不会造成死锁。
以下关于close的一些测试用例:
// channel 练习
func main() {
testChannelClose()
}
func testChannelClose() {
ch := make(chan int, 5)
ch <- 18
close(ch)
x, ok := <-ch
if ok {
fmt.Println("received: ", x)
}
x, ok = <-ch
if !ok {
fmt.Println("channel closed, data invalid.")
} else {
fmt.Println("received: ", x)
}
}
输出:
received: 18
channel closed, data invalid.
原因:channel关闭之后,原来在通道中的数据还会在缓冲区中,我们仍然还可以读出里面的数据,但是当前通道只有一个数据。所以第二次读的时候失败了。
// channel 练习
func main() {
testChannel()
}
func testChannel() {
ch := make(chan int, 5)
ch <- 18
ch <- 19
close(ch)
x, ok := <-ch
if ok {
fmt.Println("received: ", x)
}
x, ok = <-ch
if !ok {
fmt.Println("channel closed, data invalid.")
} else {
fmt.Println("received: ", x)
}
}
输出:
received: 18
received: 19
原因:channel关闭之后,原来在通道中的数据还有两个数据,这时我们还可以把这俩读出来。
如上,简单阐述了channel的一些基本用法,明天我们在列一些我们channel在实际中经常用到的一些场景