一、channel
Go 语言中的通道(channel)是一种特殊的类型。通道像一个传送带或者队列,总是遵循先入先出(First In First Out)的规则,保证收发数据的顺序。每一个通道都是一个具体类型的导管,也就是声明channel的时候需要为其指定元素类型。
channel
是 Go 语言中一种特有的类型。声明通道类型变量的格式如下:
var 变量名称 chan 元素类型
其中:
- chan:是关键字
- 元素类型:是指通道中传递元素的类型
二、实战
package main
import (
"fmt"
"time"
)
/**
chan 通道
chan 可以理解为队列,遵循先进先出的规则。
在说 chan 之前,咱们先说一下 go 关键字。
在 go 关键字后面加一个函数,就可以创建一个线程,函数可以为已经写好的函数,也可以是匿名函数。
为什么没有输出 goroutine ?
首先,我们清楚 Go 语言的线程是并发机制,不是并行机制。
那么,什么是并发,什么是并行?
并发是不同的代码块交替执行,也就是交替可以做不同的事情。
并行是不同的代码块同时执行,也就是同时可以做不同的事情。
注意:
不带缓冲的通道,进和出都会阻塞。
带缓冲的通道,进一次长度 +1,出一次长度 -1,如果长度等于缓冲长度时,再进就会阻塞。
*/
func main() {
// 声明不带缓存区的通道
ch1 := make(chan string)
// 声明带20个缓存区的通道
ch2 := make(chan string, 20)
// 声明只读缓冲区通道
//ch3 := make(<-chan string)
// 声明只写缓冲区通道
//ch4 := make(chan<- string)
// 将abc 写入通道1
//ch1 <- "abc"
//读取通道数据
//val, ok := <-ch1
//
//fmt.Println("val=,ok =", val, ok)
//val := <-ch1
//关闭通道
close(ch1)
/**
注意:
close 以后不能再写入,写入会出现 panic
重复 close 会出现 panic
只读的 chan 不能 close
close 以后还可以读取数据
*/
// ch2 写入 abc
ch2 <- "a"
go func() {
// 读取通道ch2的数据
val, ok := <-ch2
fmt.Println("val = ,ok=", val, ok)
}()
time.Sleep(1 * time.Second)
}
package main
import (
"fmt"
"time"
)
/**
chan 通道练习
*/
func main() {
fmt.Println("chan start")
ch1 := make(chan string, 5)
// goroutine 线程 go 开启任务
go producer(ch1)
go consumer(ch1)
time.Sleep(1 *time.Second)
fmt.Println("chan end")
}
func producer(ch1 chan string) {
fmt.Println(" producer ==== start")
ch1 <- "a"
ch1 <- "b"
ch1 <- "8"
ch1 <- "9"
fmt.Println("producer ==== end")
}
func consumer(ch1 chan string) {
for{
val := <- ch1
fmt.Println(val)
}
}