缓冲的 chan, make(chan int, 缓冲大小):
表示满了 缓冲大小后 就开始堵塞,无法在往 管道 塞入数据
不带缓冲区 chan,make(chan int) :
就是放入数据之后,没有取出这个数据就无法在继续放入数据
cap(ch1) 可以查看缓冲区长度
len(ch1) 可以查看缓冲区有多少未读的缓存数据
例子一
package main
import (
"fmt"
"time"
)
// 理念:不要通过共享内存来通信;通过通信来共享内存
/**
channel 例子一
channel 既然有了发送方, 就必须要有接收方!!!
*/
func worker(c chan int) {
for {
// 从 channel 里面获取数据,赋值给 n
n := <-c
fmt.Println("接收到的数据: ",n)
}
}
func chanDemo() {
// var c chan int // 此时 c == nil
// 创建一个 chan
c := make(chan int)
// 接收 channel 的数据,只能在另一个 协程(goruotime)里面才能接收到
go worker(c)
// 往 channel 发送数据
c <- 1
c <- 2
// 睡眠一下
// 因为只能打印出 1,还来不及打印 2 的时候,程序已经结束了
// 所以睡眠一下
time.Sleep(time.Millisecond)
}
func main() {
}
例子二
package main
import (
"fmt"
"time"
)
// 理念:不要通过共享内存来通信;通过通信来共享内存
/**
channel 例子二: channel数组
*/
func worker2(id int, c chan int) {
for {
// 从 channel 里面获取数据,赋值给 n
n := <-c
fmt.Println("接收到的数据: ",n)
// 发现输出的顺序不一样,这是因为,运行的时候是乱序的,谁先执行是随机的
}
}
func chanDemo2() {
// var c chan int // 此时 c == nil
var channels [10]chan int // channel 数组
for i :=0;i < 10 ;i++ {
// 创建一个 chan
channels[i] = make(chan int)
// 接收 channel 的数据,只能在另一个 协程(goruotime)里面才能接收到
go worker2(i, channels[i])
}
// 往 channel 发送数据
for i :=0;i < 10 ;i++ {
channels[i] <- 'a' + i
}
for i :=0;i < 10 ;i++ {
channels[i] <- 'A' + i
}
// 睡眠一下
// 因为只能打印出 1,还来不及打印 2 的时候,程序已经结束了
// 所以睡眠一下
time.Sleep(time.Millisecond)
}
func main() {
}
例子三
package main
import (
"fmt"
"time"
)
// 理念:不要通过共享内存来通信;通过通信来共享内存
/**
channel 例子三:把 channel 作为返回值
在使用 channel 的时候我们要告诉调用者,我这channel的方法是发送数据的,还是接收数据的
chan<- int 表示发送数据
<-chan int 表示接受数据
针对下面的例子就是:
chan<- int 表示发送数据,但是我里面同时也做了接收操作,那么我的里面就是接受数据
<-chan int 表示接受数据,但是我里面做了发送操作,那么我的里面就是发送数据
*/
// 表示一个 发送数据的channel,也就是这个 函数只能写,不能读
func createWorker3(id int) chan<- int {
// 创建一个channel
c := make(chan int)
// 需要在里一个 协程里面接收 channel 的值
// 不然这个死循环,并且还拿不到 channel 里面的值
go func() {
for {
// 从 channel 里面获取数据,赋值给 n
n := <-c
fmt.Println("接收到的数据: ",n)
// 发现输出的顺序不一样,这是因为,运行的时候是乱序的,谁先执行是随机的
}
}()
return c
}
func chanDemo3() {
// var c chan int // 此时 c == nil
var channels [10]chan<- int // channel 数组
for i :=0;i < 10 ;i++ {
// 创建一个 chan
channels[i] = createWorker3(i)
}
// 往 channel 发送数据
for i :=0;i < 10 ;i++ {
channels[i] <- 'a' + i
}
for i :=0;i < 10 ;i++ {
channels[i] <- 'A' + i
}
// 睡眠一下
// 因为只能打印出 1,还来不及打印 2 的时候,程序已经结束了
// 所以睡眠一下
time.Sleep(time.Millisecond)
}
func main() {
}
例子四
package main
import (
"fmt"
"time"
)
// 理念:不要通过共享内存来通信;通过通信来共享内存
/**
channel 例子四:
因为 channel 一个协程发送数据,另一个协程就要接收数据!
在这个过程中就要进行协程的切换比较费资源!
另一个就是我channel发送后,就要等待被接收,比较麻烦!不接受就要出问题!
*/
// 可以使用一个缓冲区的channel
// 会有性能提升
func bufferedChannel() {
// 创建一个带有缓冲区的 channel,缓冲区大小为 3
// 表示只能放 3 个数据的缓冲
c := make(chan int, 3)
// 接收者
go worker4(0, c)
c <- 'a'
c <- 'b'
c <- 'c'
c <- 'd'
time.Sleep(time.Millisecond)
}
// 关闭channel 例子
func channelClose (){
// 创建一个带有缓冲区的 channel,缓冲区大小为 3
// 表示只能放 3 个数据的缓冲
c := make(chan int, 3)
// 接收者
go worker4(0, c)
c <- 'a'
c <- 'b'
c <- 'c'
c <- 'd'
// 我发送方,告诉接收方,我发送数据完毕了,可以关闭了
// 调用 close(c) 表示关闭,关闭的标记值是 0
close(c)
time.Sleep(time.Millisecond)
}
func worker4(id int, c chan int) {
for {
// 这种方式接收,n 表示接收到的值,ok 表式是否还有数据可以接收
n, ok := <-c
if !ok {
// 表示结束这个 接收的 协程
break
}
fmt.Printf("接收到的值: %d\n", n)
}
// 这个方式也可以,等到我接收完毕,我就跳出去
// 但这个方式,只要是 发送方没有 close(c) ,就不算结束,只是我这个 for 循环自己跳出了而已
// 然后等到我这个 main 主函数结束后,我发送方的 协程才算结束
//for n := range c{
// fmt.Printf("接收到的值: %d\n", n)
//}
}
func main() {
}