channel

创建

声明

var ch chan int

赋值

无缓冲 channel:元素类型为 T

ch1 := make(chan int)   

带缓冲 channel:元素类型为 T、缓冲区长度为 capacity

ch2 := make(chan int, 5) 

发送与接收

ch1 <- 13    // 将整型字面值13发送到无缓冲channel类型变量ch1中
n := <- ch1  // 从无缓冲channel类型变量ch1中接收一个整型值存储到整型变量n中
ch2 <- 17    // 将整型字面值17发送到带缓冲channel类型变量ch2中
m := <- ch2  // 从带缓冲channel类型变量ch2中接收一个整型值存储到整型变量m中


ch3 := make(chan<- int, 1) // 只发送channel类型
ch4 := make(<-chan int, 1) // 只接收channel类型

channel 是用于 Goroutine 间通信的

Goroutine 对无缓冲 channel 的接收和发送操作是同步的。也就是说,对同一个无缓冲 channel,只有对它进行接收操作的 Goroutine 和对它进行发送操作的 Goroutine 都存在的情况下,通信才能得以进行,否则单方面的操作会让对应的 Goroutine 陷入挂起状态

对无缓冲 channel 类型的发送与接收操作,一定要放在两个不同的 Goroutine 中进行,否则会导致 deadlock

带缓冲 channel 的运行时层实现带有缓冲区,因此,对带缓冲 channel 的发送操作在缓冲区未满、接收操作在缓冲区非空的情况下是异步的(发送或接收不需要阻塞等待)。

例子:启动两个 Goroutine,分别代表生产者(produce)与消费者(consume)。生产者只能向 channel 中发送数据;消费者只能从 channel 中接收数据

package main

import (
	"sync"
	"time"
)

func produce(ch chan<- int) {
	for i := 0; i < 10; i++ {
		ch <- i + 1
		time.Sleep(time.Second)
	}
	close(ch)
}
func consume(ch <-chan int) {
	for n := range ch {
		println(n)
	}
}
func main() {
	ch := make(chan int, 5)
	var wg sync.WaitGroup
	wg.Add(2)
	go func() {
		produce(ch)
		wg.Done()
	}()
	go func() {
		consume(ch)
		wg.Done()
	}()
	wg.Wait()
}

注意:发送端负责关闭 channel

select

select {
case x := <-ch1:     // 从channel ch1接收数据
  ... ...
case y, ok := <-ch2: // 从channel ch2接收数据,并根据ok值判断ch2是否已经关闭
  ... ...
case ch3 <- z:       // 将z值发送到channel ch3中:
  ... ...
default:             // 当上面case中的channel通信均无法实施时,执行该默认分支
}
posted @ 2022-03-22 14:45  请务必优秀  阅读(555)  评论(1编辑  收藏  举报