目录
- 有无缓冲的区别
- channel 无缓冲
- channel 带缓存
有无缓冲的区别
形象说明一下无缓冲和有缓冲的区别:
无缓冲是同步的,例如 make(chan int),就是一个送信人去你家门口送信,你不在家他不走,你一定要接下信,他才会走,无缓冲保证信能到你手上。
有缓冲是异步的,例如 make(chan int, 1),就是一个送信人去你家仍到你家的信箱,转身就走,除非你的信箱满了,他必须等信箱空下来,有缓冲的保证信能进你家的邮箱。
channel 无缓冲
例1:
- func main() {
- ch := make(chan int)
- ch <- 1 // 报错,因为ch 无缓冲,存一个就必须立即取出来
- fmt.Println(<- ch)
- }
复制代码改正: - func main() {
- ch := make(chan int)
- go tt(ch) // 开一个 goroutine
- fmt.Println("我先执行1111")
- fmt.Println(<-ch) // 因为前面开了一个 goroutine, 这一行比 go tt(ch) 先执行,这里堵塞了,等到 tt(ch) 中的语句执行完之后,本行执行
- // 我先执行1111
- // 我先执行2222
- // 1
- }
-
- func tt(ch chan int) {
- fmt.Println("我先执行2222")
- ch <- 1
- }
复制代码 例2:
- package main
-
- import "fmt"
-
- func main() {
- ch := make(chan int) // 无缓冲的channel
- go unbufferChan(ch)
-
- for i := 0; i < 10; i++ {
- fmt.Println("receive ", <-ch) // 读出值
- }
- }
-
- func unbufferChan(ch chan int) {
- for i := 0; i < 10; i++ {
- fmt.Println("send ", i)
- ch <- i // 写入值
- }
- }
-
- // 输出
- // send 0
- // send 1
- // receive 0
- // receive 1
- // send 2
- // send 3
- // receive 2
- // receive 3
- // send 4
- // send 5
- // receive 4
- // receive 5
- // send 6
- // send 7
- // receive 6
- // receive 7
- // send 8
- // send 9
- // receive 8
- // receive 9
复制代码 channel 带缓存
例1:
放的速度较快,先放满了 5 个,阻塞住;取的速度较慢,放了5个才开始取,由于缓冲区已经满了,所以取出一个之后,才能再次放入;放完了之后虽然缓冲区关闭了,但是缓冲区的内容还保留,所以还能继续取出 - func put(c chan int) {
- for i := 0; i < 10; i++ {
- c <- i
- time.Sleep(100 * time.Millisecond)
- fmt.Println("->放入", i)
- }
- fmt.Println("=所有的都放进去了!关闭缓冲区,但是里面的数据不会丢失,还能取出。")
- close(c)
- }
-
- func main() {
- ch := make(chan int, 5)
- go put(ch)
- for {
- time.Sleep(1000 * time.Millisecond)
- data, ok := <-ch
- if ok == true {
- fmt.Println("<-取出", data)
- } else {
- break
- }
- }
- }
-
- // ->放入 0
- // ->放入 1
- // ->放入 2
- // ->放入 3
- // ->放入 4
- // <-取出 0
- // ->放入 5
- // <-取出 1
- // ->放入 6
- // <-取出 2
- // ->放入 7
- // <-取出 3
- // ->放入 8
- // <-取出 4
- // ->放入 9
- // =所有的都放进去了!关闭缓冲区,但是里面的数据不会丢失,还能取出。
- // <-取出 5
- // <-取出 6
- // <-取出 7
- // <-取出 8
- // <-取出 9
复制代码 例2:一边存,一边取
- package main
-
- import"fmt"
-
- var c = make(chan int, 5)
-
- func main() {
- go worker(1)
- for i := 1; i < 10; i++ {
- c <- i
- fmt.Println(i)
- fmt.Println("cap = ", cap(c), " len = ", len(c))
- }
- }
-
- func worker(id int) {
- for {
- _ = <-c
- }
- }
-
- // 运行输出:
- // 1
- // cap = 5 len = 0
- // 2
- // cap = 5 len = 0
- // 3
- // cap = 5 len = 1
- // 4
- // cap = 5 len = 2
- // 5
- // cap = 5 len = 0
- // 6
- // cap = 5 len = 1
- // 7
- // cap = 5 len = 2
- // 8
- // cap = 5 len = 2
- // 9
- // cap = 5 len = 0
复制代码到此这篇关于详解golang channel有无缓冲区的区别的文章就介绍到这了,更多相关golang channel缓冲区内容请搜索晓枫资讯以前的文章或继续浏览下面的相关文章希望大家以后多多支持晓枫资讯!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |