1. channel
goroutine 之间通信的通道就叫做 channel
1.1 创建使用 channel
定义一个 channel 类型:
var c chan int // c == nil
创建一个 channel:
c := make(chan int)
向一个 channel 发送数据:
c <- 1 // 将1发送给 channel 实例
接收一个 channel 发送的数据:
n := <-c
综合示例如下:
func chanDemo() {
c := make(chan int)
go func() {
for {
n := <-c
fmt.Println(n)
}
}()
c <- 1 // 如果发送一个channel却无人接收,那么就会产生死锁
c <- 2
time.Sleep(time.Millisecond)
}
func main() {
chanDemo()
}
我们可以单独将 goroutine 抽离出来从而创建多个 goroutine,并建立多个 channel:
func worker(id int, c chan int) {
for {
fmt.Printf("Worker %d received %d\n", id, <-c)
}
}
func chanDemo() {
var channels [10]chan int
for i := 0; i < 10; i++ {
channels[i] = make(chan int)
go worker(i, channels[i])
}
for i := 0; i < 10; i++ {
channels[i] <- i
}
time.Sleep(time.Millisecond)
}
func main() {
chanDemo()
}
同时创建 goroutine 与生成一个 channel 的步骤可以合并为一个步骤,返回的对象为一个 channel:
func createWorker(id int) chan int {
c := make(chan int)
go func() {
for {
fmt.Printf("Worker %d received %d\n", id, <-c)
}
}()
return c
}
定义channel类型时,我们可以规定其只能接受数据或者只能发送数据:
channel := make(chan<- int) // channel 只能接收数据
channel := make(<-chan int) // channel 只能发送
这样的操作通常用于返回一个仅可以接收数据的channel。
1.2 使用 BufferChanel
使用了 buffer channel 后,会创建一个缓冲区,不必等待 channel 的接收者,因此可以接受数条数据并不让系统发生死锁,如下的的程序是合法的:
func bufferedChannel() {
c := make(chan int, 3)
c <- 1
c <- 2
c <- 3
// c <- 4 超出缓冲区的部分却无接收对象的数据会让系统产生死锁
}
创建缓冲区可以优化性能,但是与平常的使用无异。
1.3 使用 close() 函数关闭 channel
使用 close(c chan<- Type)
方法可以用来关闭一个channel:
func channelClose() {
c :=