目录
2、fatal error: all goroutines are asleep - deadlock!
1、Channel
在Go语言中,Channel(通道)是用于goroutine之间进行通信和同步的一种机制。它可以在一个goroutine中发送数据到通道,然后在另一个goroutine中接收数据。通道是类型相关的,也就是说通道中传输的数据必须是同一类型。
channel是一种类型,一种引用类型。声明通道类型的格式如下:
var 变量 chan 元素类型
通道是引用类型,通道类型的空值是nil。
var ch chan int
fmt.Println(ch) // <nil>
声明的通道后需要使用make函数初始化之后才能使用。
package main
import "fmt"
func main() {
var f chan int
fmt.Println(f)
f = make(chan int)
fmt.Println(f)
}
2、fatal error: all goroutines are asleep - deadlock!
package main
import "fmt"
func main() {
var f chan int
fmt.Println(f)
f = make(chan int)
fmt.Println(f)
f <- 10
}
为什么会出现deadlock错误呢?
因为我们使用ch := make(chan int)创建的是无缓冲的通道,无缓冲的通道只有在有人接收值的时候才能发送值。
就像你住的小区没有快递柜和代收点,快递员给你打电话必须要把这个物品送到你的手中,简单来说就是无缓冲的通道必须有接收才能发送。
那如何解决这个问题呢?
一种方法是启用一个goroutine去接收值,例如:
package main
import "fmt"
func recv(c chan int) {
ret := <-c
fmt.Println("接收成功", ret)
}
func main() {
var f chan int
fmt.Println(f)
f = make(chan int)
fmt.Println(f)
go recv(f)
f <- 10
}
无缓冲通道上的发送操作会阻塞,直到另一个goroutine在该通道上执行接收操作,这时值才能发送成功,两个goroutine将继续执行。相反,如果接收操作先执行,接收方的goroutine将阻塞,直到另一个goroutine在该通道上发送一个值。
使用无缓冲通道进行通信将导致发送和接收的goroutine同步化。因此,无缓冲通道也被称为同步通道。
3、有缓冲的通道
我们可以在使用make函数初始化通道的时候为其指定通道的容量,例如:
package main
import "fmt"
func main() {
ch := make(chan int, 1) // 创建一个容量为1的有缓冲区通道
ch <- 10
fmt.Println("发送成功")
}
只要通道的容量大于零,那么该通道就是有缓冲的通道,通道的容量表示通道中能存放元素的数量。就像你小区的快递柜只有那么个多格子,格子满了就装不下了,就阻塞了,等到别人取走一个快递员就能往里面放一个。