详解golang channel有无缓冲区的区别

 更新时间:2024年01月29日 10:47:07   作者:壮Sir不壮  
这篇文章主要给大家介绍了golang 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缓冲区内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 深入剖析Go语言编程中switch语句的使用

    深入剖析Go语言编程中switch语句的使用

    这篇文章主要介绍了Go语言编程中switch语句的使用,是Go语言入门学习中的基础知识,需要的朋友可以参考下
    2015-10-10
  • 深入了解Golang官方container/list原理

    深入了解Golang官方container/list原理

    在 Golang 的标准库 container 中,包含了几种常见的数据结构的实现,其实是非常好的学习材料,本文主要为大家介绍了container/list的原理与使用,感兴趣的可以了解一下
    2023-08-08
  • 6行代码快速解决golang TCP粘包问题

    6行代码快速解决golang TCP粘包问题

    在用golang开发人工客服系统的时候碰到了粘包问题,那么什么是粘包呢?下面这篇文章主要给大家介绍了关于如何通过6行代码快速解决golang TCP粘包问题的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴下面随着小编来一起学习学习吧。
    2018-03-03
  • Go定时器cron的使用详解

    Go定时器cron的使用详解

    本篇文章主要介绍了Go定时器cron的使用详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • Go实现生产随机密码的示例代码

    Go实现生产随机密码的示例代码

    这篇文章主要为大家详细介绍了如何利用Go实现生产随机密码的,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以参考一下
    2023-09-09
  • Go语言将string解析为time.Time时两种常见报错

    Go语言将string解析为time.Time时两种常见报错

    本文主要介绍了Go语言将string解析为time.Time时两种常见报错,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • golang 结构体初始化时赋值格式介绍

    golang 结构体初始化时赋值格式介绍

    这篇文章主要介绍了golang 结构体初始化时赋值格式介绍,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • windows下安装make及使用makefile文件

    windows下安装make及使用makefile文件

    这篇文章主要为大家介绍了windows下安装make及使用makefile文件方法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • Go语言读取,设置Cookie及设置cookie过期方法详解

    Go语言读取,设置Cookie及设置cookie过期方法详解

    这篇文章主要介绍了Go语言读取,设置Cookie及设置cookie过期方法详解,需要的朋友可以参考下
    2022-04-04
  • Go 常量基础概念(声明更改只读)

    Go 常量基础概念(声明更改只读)

    这篇文章主要为大家介绍了Go常量基础概念包括常量的声明更改只读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08

最新评论