Go并发编程Channel

作者: TZX_0710 | 来源:发表于2021-08-06 19:50 被阅读0次

Channel

单纯地将函数并发执行是没有意义地,函数与函数需要交换数据才能体现并发执行函数地意义。

Go语言的并发模型是CSP,提倡通过通信共享内存而不是通过共享内存实现通信。如果goroutine是并发地执行体,channle就是它们之间的连接。channel是可以让一个goroutine发送特定值到另一个goroutine的通信机制。

Go语言中的通道是一种特殊的类型。通道像一个传送带或者队列,总是遵循先入先出的规则,保证收发顺序。每一个通道都是一个具体类型的导管,也就是声明channel的时候需要为其指定元素类型。

channel类型

channel是一种类型一种引用类型。

var 变量名 chan 元素类型
var ch1 chan bool //声明一个传递布尔类型的通道
var ch2 chan int //声明一个传递整形的通道
var ch3 chan string //声明一个传递字符串的通道

创建channel

通道是引用类型,通道类型的空值是nill

var ch chan int 
//声明后的通道需要使用make进行初始化才能使用
package main

import (
  "fmt"
  "time"
)

func sendMsg(ch chan bool) {
  //写入true到ch通道
  ch <- true
}
func main() {
  //fatal error: all goroutines are asleep - deadlock!
  var ch1 chan bool
  //无缓存通道
  //fatal error: all goroutines are asleep - deadlock!
  //使用如下方式创建通道发送数据会发生的错误
    //原因是无缓冲通道必须要有人接受值得时候才能发送值。
  //第一种方法是采用make(chan bool,1) 创建带缓冲的通道
  //第二种方法就是采用另一个goroutine对该通道进行操作
  //创建的是无缓存通道,无缓冲通道的只要有人接受值的时候才能发送值。
  ch1 = make(chan bool)
  //ch1 <- true
  go sendMsg(ch1)
  //从ch1通道读取参数
  fmt.Println(<-ch1)
  time.Sleep(time.Second * 3)

}
fmt.Println(ch)//nil

从通道循环取值

package main

import "fmt"

func main() {
  //创建无缓冲通道
  ch1 := make(chan int)
  ch2 := make(chan int)
  go func() {
      for i := 0; i < 10; i++ {
          //向ch1写入数据
          ch1 <- i
      }
      //当通道不再需要写入一定要close() 关闭通道!
      close(ch1)
  }()
  go func() {
      for true {
          i, ok := <-ch1 //chan在ch1通道关闭之后 ok的值就变成了false  i就变成了0值当channel关闭且数据都读完了,再读数据会读到该数据类型的零值,且第二个返回值为false
          if !ok {
              break
          }
          ch2 <- i * i //向ch2写入数据
      }
      close(ch2) //关闭ch2通道
  }()
  for i := range ch2 {
      fmt.Println(i)
  }
}

单向通道

有时候在将通道作为参数在多个任务函数间传递,很多时候我们在不同的任务函数中使用通道都会对其进行限制比如限制通道在函数中只能发送或者接受。

//语法 
chan <-int  可以写入的通道
<-chan int 只可以读取的通道
package main

import "fmt"

func write(out chan<- int) {
  //写入该通道
  for i := 0; i < 10; i++ {
      out <- i
  }
  close(out)
}

//交换通道数据
//out 是可以写入的数据 in是只能读取的通道
func square(out chan<- int, in <-chan int) {
  for i := range in {
      out <- i
  }
  close(out)
}
func main() {
  //在函数传参及任何赋值操作中将双向通道转换为单向通道是可以的,但反过来是不可以的。
  //创建2个通道
  ch1 := make(chan int)
  ch2 := make(chan int)
  //ch1被转换成了只可写入的通道
  go write(ch1)
  //ch2变成了可写入 ch1变成了只可读取
  go square(ch2, ch1)
  for i := range ch2 {
      fmt.Println(i)
  }
}

相关文章

  • Go 专栏|并发编程:goroutine,channel 和 s

    原文链接: Go 专栏|并发编程:goroutine,channel 和 sync[https://mp.weix...

  • Go并发编程Channel

    Channel 单纯地将函数并发执行是没有意义地,函数与函数需要交换数据才能体现并发执行函数地意义。Go语言的并发...

  • go并发通信

    go并发编程时,请记住:“不要通过共享内存来通信,而应该通过通信来共享内存” channel是Go语言在语言级别提...

  • 小试牛刀

    go 使并发编程变得简单 当一个 channel 被 close 后再 send 会 panic, 再取值不会阻塞...

  • go channel详解之源码分析

    作为golang并发编程思想的重要组成,channel(通道)非常重要,和goroutine(go协程)一起使用,...

  • Go的并发机制:线程模型

    目录 一、 Go的并发机制:线程模型二、 Go的并发机制:goroutine和channel[https://ww...

  • Go并发编程-channel多路复用

    在前面两篇文章中,已经详细的介绍了 goroutine 和 channel,它们是 Go 并发编程的基础。今天这篇...

  • 关于Golang的那些事(七)-- goroutine和通道

    Go有两种并发编程的风格。这一章展示goroutine和通道(channel),它们支持通信顺序进程,CSP...

  • go语言并发操作

    go语言实现并发 通过go 实现并发操作 执行上述代码,会间隔执行say方法 通过channel实现并发数据间的通...

  • go入门(七)2018-07-19

    go并发 goroutine Go运行环境管理的轻量级线程go xxx 启动新的goroutine channel...

网友评论

    本文标题:Go并发编程Channel

    本文链接:https://www.haomeiwen.com/subject/coxivltx.html