Golang进阶之关于channel全面分析(三)

关于通道缓存

关于通道缓存,为了方便理解我暂时可理解为通道的数组,特性慢慢分析下

先学习通道的关闭

通道关闭,意味着不能在往通道发数据了.但是还可以接收数据.

package main

import "fmt"

func main() {
    jobs := make(chan int, 5)
    done := make(chan bool)

    go func() {
        for {
            j, more := <-jobs
           	//more在通道已经关闭并且所有的信息都已经被接受情况下为false
            if more {
                fmt.Println("完成工作:", j)
            } else {
                fmt.Println("工作全部完成")
                done <- true
                return
            }
        }
    }()


    for j := 1; j <= 3; j++ {
        jobs <- j
        fmt.Println("布置工作:", j)
    }
    close(jobs)
    fmt.Println("关闭通道")

    // <-done这里是之前单通道的特性,用于等待协程完工,否则程序直接结束了 
    <-done
}
/*打印的结果为
布置工作: 1
布置工作: 2
布置工作: 3
关闭通道
完成工作: 1
完成工作: 2
完成工作: 3
工作全部完成

为了更直观的分析 关闭通道我们这么来进行测试

package main

import (
	"fmt"
	"time"
)

func main() {
	jobs := make(chan int, 5)


	go func() {
		for {
			fmt.Println("接收方协程开始工作:")
			j := <-jobs
			time.Sleep(time.Second*1)
			fmt.Println("完成工作:", j)
		}
	}()


	time.Sleep(time.Second*3)

	for j := 1; j <= 3; j++ {
		jobs <- j
		fmt.Println("布置工作:", j)

	}
close(jobs)
fmt.Println("完成工作并关闭通道,")

	time.Sleep(time.Second*20)
/*
接收方协程开始工作:
布置工作: 1
布置工作: 2
布置工作: 3
完成工作并关闭通道,
完成工作: 1
接收方协程开始工作:
完成工作: 2
接收方协程开始工作:
完成工作: 3
接收方协程开始工作:
完成工作: 0
接收方协程开始工作:
完成工作: 0
...
}

一旦关闭通道接收方没处理的话会无限循环下去.

遍历通道

package main

import (
	"fmt"
	"time"
)

func main() {

	queue := make(chan string, 2)

	go func() {
		for elem := range queue {
			fmt.Println(elem)
		}
		fmt.Println("完成了下一步")

	}()

	queue <- "one"
	queue <- "two"
	//close(queue)

	time.Sleep(time.Second*2)
	queue <- "111"
	close(queue)
	time.Sleep(time.Second*10)
/*如果将close(queue) 注释掉 那么协程将会继续阻塞到接受第四个值

}

这个例子如果使用 elem:=<- queue 来接受数据的话
那么我们能输入进通道的数据 就是缓存数+ <- queue 的个数 否则就要报错

range就相当于在接收方就相当于无限,发送方可以无限发送数据

上一篇:由浅入深剖析 go channel


下一篇:go 多线程并发 queue demo