(18条消息) Go语言自学系列 | golang并发变成之通道channel_COCOgsta的博客-CSDN博客



Go语言自学系列 | golang并发变成之通道channel

COCOgsta 已于 2022-04-09 21:01:03 修改 39 收藏
分类专栏: 视频学习笔记 文章标签: golang go

视频来源:B站《golang入门到项目实战 [2021最新Go语言教程,没有废话,纯干货!持续更新中...]》

一边学习一边整理老师的课程内容及试验笔记,并与大家分享,侵权即删,谢谢支持!

附上汇总贴:Go语言自学系列 | 汇总_COCOgsta的博客-CSDN博客


Go提供了一种称为通道的机制,用于在goroutine之间共享数据。当您作为goroutine执行并发活动时,需要在goroutine之间共享资源或数据,通道充当goroutine之间的管道(管道)并提供一种机制来保证同步交换。

需要在声明通道时指定数据类型。我们可以共享内置、命名、结构和引用类型的值和指针。数据在通道上传递:在任何给定时间只有一个goroutine可以访问数据项:因此按照设计不会发生数据竞争。

根据数据交换的行为,有两种类型的通道:无缓冲通道和缓冲通道。无缓冲通道用于执行goroutine之间的同步通信,而缓冲通道用于执行异步通信。无缓冲通道保证在发送和接收发生的瞬间两个goroutine之间的交换。缓冲通道没有这样的保证。

通道由make函数创建,该函数指定chan关键字和通道的元素类型。

这是创建无缓冲和缓冲通道的代码块:

语法

  1. 1
    Unbuffered := make(chan int) // 整型无缓冲通道
  2. 2
    buffered := make(chan int, 10) // 整型有缓冲通道

使用内置函数make创建无缓冲和缓冲通道。make的第一个参数需要关键字chan,然后是通道允许交换的数据类型。

这是将值发送到通道的代码块需要使用<-运算符:

语法

  1. 1
    goroutine1 := make(chan string, 5) // 字符串缓冲通道
  2. 2
    goroutine1 <- "Australia" // 通过通道发送字符串

一个包含5个值的缓冲区的字符串类型的goroutine1通道。然后我们通过通道发送字符串“Australia”。

这是从通道接收值的代码块:

语法

data := <- goroutine1 // 从通道接收字符串 

<- 运算符附加到通道变量(goroutine1)的左侧,以接收来自通道的值。

无缓冲通道

在无缓冲通道中,在接收到任何值之前没有能力保存它。在这种类型的通道中,发送和接收goroutine在任何发送或接收操作完成之前的同一时刻都准备就绪。如果两个goroutine没有在同一时刻准备好,则通道会让执行其各自发送或接收操作的goroutine首先等待。同步是通道上发送和接收之间交互的基础。没有另一个就不可能发生。

缓冲通道

在缓冲通道中,有能力在接收到一个或多个值之前保存它们。在这种类型的通道中,不要强制goroutine在同一时刻准备好执行发送和接收。当发送和接收阻塞时也有不同的条件。只有当通道中没有要接收的值时,接收才会阻塞。仅当没有可用缓冲区来放置正在发送的值时,发送才会阻塞。

通道的发送和接收特性

  1. 对于同一个通道,发送操作之间是互斥的。接收操作之间也是互斥的。
  2. 发送操作和接收操作中对元素值的处理都是不可分割的。
  3. 发送操作在完全完成之前会被阻塞。接收操作也是如此。

实例

  1. 1
    package main
  2. 2
  3. 3
    import (
  4. 4
    "fmt"
  5. 5
    "math/rand"
  6. 6
    "time"
  7. 7
    )
  8. 8
  9. 9
    // 创建int类型通道,只能传入int类型值
  10. 10
    var values = make(chan int)
  11. 11
  12. 12
    func send() {
  13. 13
    rand.Seed(time.Now().UnixNano())
  14. 14
    value := rand.Intn(10)
  15. 15
    fmt.Printf("send: %v\n", value)
  16. 16
    // time.Sleep(time.Second * 5)
  17. 17
    values <- value
  18. 18
    }
  19. 19
  20. 20
    func main() {
  21. 21
    // 从通道接收值
  22. 22
    defer close(values)
  23. 23
    go send()
  24. 24
    fmt.Println("wait...")
  25. 25
    value := <-values
  26. 26
    fmt.Printf("receive: %v\n", value)
  27. 27
    fmt.Println("end...")
  28. 28
    }
  29. 29

运行结果

  1. 1
    [Running] go run "d:\SynologyDrive\软件开发\go\golang入门到项目实战\goproject\360duote.com\pro01\test.go"
  2. 2
    wait...
  3. 3
    send: 8
  4. 4
    receive: 8
  5. 5
    end...


yg9538 2022年7月22日 22:48 836 收藏文档