🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
### 上周的课程我们了解到了原子锁和互斥锁,都可以保证共享数据的读写,但是它们还是有点复杂,而且影响性能,对此,Go又为我们提供了一种工具,这就是通道,goroutine 运行的时候是相互独立的。使用关键字 go 创建 goroutine 来运行函数。 ### 一个死锁的例子: ` var ch1 chan int = make(chan int) var ch2 chan int = make(chan int) func say(s string) { fmt.Println(s) ch1 <- <- ch2 // ch1 等待 ch2流出的数据 } func main() { go say("hello") <- ch1 // 堵塞主线 } ` ### 所以在多个goroutine并发中,我们可以通过使用通道,在多个goroutine发送和接受共享的数据,达到数据同步的目的。 ### 通道,他有点像在两个goroutine之间架设的管道,一个goroutine可以往这个管道里塞数据,另外一个可以从这个管道里取数据,有点类似于我们说的队列。 ` 通道的声明方式 ch:=make(chan int) ` ### 通道类型和Map这些类型一样,可以使用内置的 make 函数声明初始化,这里我们初始化了一个 chan int 类型的通道,所以我们只能往这个通道里发送 int 类型的数据,当然接收也只能是 int 类型的数据。 ### 通道是用于在goroutine之间通信的,它具有发送和接收两个操作。 `ch <- 2 //发送数值2给这个通道 x:=<-ch //从通道里读取值,并把读取的值赋值给x变量 <-ch //从通道里读取值,然后忽略 ` ### 我们使用内置的 close 函数来关闭通道 ### select总结 select是Go中的一个控制结构,类似于switch语句。select可以监听多个channel的读写事件,当case中channel读写操作为非阻塞状态(即能读写)时,将会触发相应的动作。 1、如果有多个case都可以运行,select中对case语句的判断不是顺序进行的,select会随机公平地选出一个执行,其他不会执行。 2、如果没有可运行的case语句,且有default语句,那么就会执行default的动作。 3、如果没有可运行的case语句,且没有default语句,select将阻塞,直到某个case通信可以运行