这是我参与「第五届青训营 」伴学笔记创作活动的第 11 天
声明和存取
channel,是一种带有类型的管道引用类型
使用前需要make(Type, (缓冲容量))
不带缓冲区的管道必须结合协程使用
可以查看长度len和容量cap
package mainimport "fmt"func main() { // 声明一个string信道,容量为2 var ch chan string = make(chan string, 2) ch <- "枫枫" // 写入数据到信道中 ch <- "知道" s := <-ch // 从信道读取数据 fmt.Println(s) ss, ok := <-ch fmt.Println(ss, ok) close(ch)}
存入:channel <- value取出:value, (ok) <- channel丢弃:<- channel先进先出,自动阻塞数据需要保持流动,否则会阻死报错
搭配协程使用
package mainimport "fmt"func pushNum(c chan int) { for i := 0; i < 100; i++ { c <- i } close(c) // 写完必须要关闭,不然会死锁}func main() { var c1 chan int = make(chan int, 2) // 2表示缓冲区大小 go pushNum(c1) for value := range c1 { fmt.Println(value) }}
多个协程函数,close就不能写在协程函数里了
package mainimport ( "fmt" "sync")var ch chan int = make(chan int, 10)var wg = sync.WaitGroup{}func pushNum() { for i := 0; i < 5; i++ { ch <- i } wg.Done()}func main() { wg.Add(2) go pushNum() go pushNum() wg.Wait() close(ch) for { res, ok := <-ch if !ok { break } fmt.Println(res) }}
close
使用close之后就不能在继续写入了,但是还可以继续从缓冲区读取
- close之后,读取的chan是数据类型的默认值
- close之后,不能再往chan里面写入数据
- for range之前必须要close
可读可写
package mainimport "fmt"func main() { var ch chan int = make(chan int, 2) // 可读chan var readCh <-chan int = ch // 可写chan var writeCh chan<- int = ch writeCh <- 1 writeCh <- 2 fmt.Println(<-readCh) fmt.Println(<-readCh)}
select … case
适用于无法确认合适关闭信道的情况
通常结合for循环使用
select … case会阻塞到某个分支可以继续执行时执行该分支,当没有可执行的分支是执行default分支
package mainimport "fmt"func main() { var ch1 chan int = make(chan int, 2) var ch2 chan int = make(chan int, 2) var ch3 chan int = make(chan int, 2) ch1 <- 1 ch2 <- 2 ch3 <- 3 select { // 监听多个chan的情况,是随机执行 case v := <-ch1: fmt.Println(v) case v := <-ch2: fmt.Println(v) case v := <-ch3: fmt.Println(v) default: fmt.Println("没有数据") }}
package mainimport "fmt"func PrimeNum(n int, c chan int) { for i := 2; i < n; i++ { if n%i == 0 { return } } c <- n}func main() { c := make(chan int) for i := 2; i < 100001; i++ { go PrimeNum(i, c) }Print: for { select { case v := <-c: fmt.Printf("%v\t", v) default: fmt.Printf("所有素数都已被找到") break Print } }}