1、管道的定义
func main(){
// chan
// channel
// 管道中放什么类型需要提前执行
// 声明int类型的管道channel
var channel chan int
// 初始化&赋值
// make()
channel :=make(chan int) //无缓冲区管道
}
2、管道的读和写
func main(){
channel:=make(chan int) //无缓冲区管道读和写不能在同一个例程里面
go func(){ //工作例程写入管道
channel<-1 //将1写入管道,在写入管道后,如果还没有读管道,会发生阻塞
} ()
//主例程读管道
num<-channel //将管道值读入变量,如果未读到数据也会发生阻塞
}
注意:必须有两个例程一个写一个读,否则管道会产生死锁
3、关闭管道
close(channel) //关闭管道
go func(){
fmt.Println(<-channel)
}
channel<-1
关闭之后的管道是不能够写的,但是可以读,值为空
4、判断管道是否关闭
v,ok:=<-channel //用两个值来判断key是不是存在
5、使用for range 来遍历管道
func main(){
channe:=make(chan int)
for func(){}
channel<-1
channel<-2
channel<-3
}()
for num:=range channel{
fmt.Println(num)
}
}
上面的结果会产生死锁,如果要结束死锁可以使用close来关闭管道,如下:
func main(){
channe:=make(chan int)
for func(){}
channel<-1
channel<-2
channel<-3
close(channel)
}()
for num:=range channel{
fmt.Println(num)
}
}
6、带缓冲的管道
//声明方式
channel := make(chan int,3) //channel可以放三个值
带缓冲的管道也可以用close的方式终止遍历而不产生死锁,也可以使用遍历同等数量的值来避免死锁。示例:
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println("start")
channel := make(chan int)
cnt := 2
go func() {
for i := 'A'; i <= 'Z'; i++ {
fmt.Printf("%c\n", i)
runtime.Gosched()
}
channel <- 0
}()
go func() {
for i := 1; i <= 10; i++ {
fmt.Printf("%d\n", i)
runtime.Gosched()
}
channel <- 0
}()
// time.Sleep(3 * time.Second)
for i := 0; i < cnt; i++ { //使用同等量的值来规避死锁
<-channel
}
fmt.Println("end")
}
文档更新时间: 2021-08-21 15:45 作者:张尚