跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • Golang channe 你知多少
未分類
2020 年 11 月 24 日

Golang channe 你知多少

Golang channe 你知多少

資深大佬 : haicoderibai 5

原文地址:嗨客网

Golang channel 使用

Golang channel 使用教程

在 golang 中 channel 用于 goroutine 之间的通信,channel 是引用类型,需要使用 make 来创建 channel 。在 Golang 中,用通信来共享内存,而不要用共享内存来通信。

channel 创建详解

语法

ch := make(chan Type, [buffer]) 

参数

ch: 创建的 channel 类型的变量 Type: channel 的类型 buffer: channel 缓冲区大小

说明

make 对于 channel 接收两个参数,第一个是通道的类型,第二个是个可选参数代表通道缓冲区的大小(省略代表无缓冲)。

无缓冲 channel

ch := make(chan int) 

带缓冲 channel

ch := make(chan int, 2) 

channel 写入数据

说明

我们可以使用 <- 符号指向 channel 来将元素放入 channel 中,注意向通道中传值必须要求该通道还有容量(缓冲),而且通道不能关闭。

对于无缓冲的或者缓冲已经满了的 channel 不可以轻易的传入值,必须要有 goroutine 同时在取元素才可以放入。

示例

向一个有缓冲,非满的 channel 传值

c := make(chan int, 1) // 定义一个带有一个缓冲的通道 c <- 1   // 向通道中传入一个 1,正常 

向一个有缓冲,满的 channel 传值

c := make(chan int, 1) // 定义一个带有一个缓冲的通道 c <- 1                 // 向通道中传入一个值,这个值传入后填满了该通道 c <- 2                 // 再向通道中传入一个值,报错 

向一个无缓冲的 channel 传值

c := make(chan int) // 定义一个无缓冲通道 c <- 1              // 向无缓冲通道传值,报错 

其实上述两种错误均是由于通道满了而引起的(无缓冲的通道可以看成是缓冲为 0 的通道),解决方法很简单,只要保证有个 goroutine 同时在从该通道中取值即可。

channel 读取数据

说明

我们可以使用 <- 符号指向变量来将 channel 中的元素放变量中,此时可以接收两个值一个数值一个状态,如下代码:

v, ok := <-c   // c 是通道,v 是取到的值,ok 是状态,正常时是 true,从关闭的空通道取值是 false 

对于无缓冲的或者缓冲已经空了的 channel 不可以轻易的取出值,必须要同时在放元素才可以取出。

示例

ok 为 true 的例子

c := make(chan int, 1) c <- 1 a, ok := <-c fmt.Println(a, ok)  // 输出 1 true 

ok 为 false 的例子

c := make(chan int, 1) close(c) a, ok := <-c fmt.Println(a, ok)  // 输出 0 false 

ok 的应用–循环取值

for {     v, ok := <- c     if !ok {         break     }     fmt.Println(v) } 

range 取值

func main() {     c := make(chan int, 10)      for i:=0; i< 10; i++ {         c <- i     }     close(c)      for v := range c{         fmt.Println(v)     } } 

向一个有缓冲,非空的 channel 取值

c := make(chan int, 1) // 定义一个带有一个缓冲的通道 c <- 1                 // 向通道中传入一个 1,使通道非空 i := <-c               // 从通道中取出一个值赋给变量 i // 如果只是想取出值而不想对该值做任何其他操作,可以这么写   <-c   左边省略接收者 

向一个有缓冲,空的 channel 取值

c := make(chan int, 1) // 定义一个带有一个缓冲的通道 <-c                    // 向空通道中取出一个值,报错 

向一个无缓冲的 channel 取值

c := make(chan int) // 定义一个无缓冲通道 <-c                 // 向无缓冲通道取值,报错 

其实上述两种错误均是由于通道空了而引起的(无缓冲的通道可以看成是缓冲为 0 的通道),解决方法很简单,只要保证同时在从该通道中存值即可。

关闭 channel 详解

说明

对于一个通道我们可以使用 close 内置函数来进行关闭,关闭后的通道具有以下特点:

  • 向一个已经关闭的通道发送值是不允许的,会报错
  • 从一个已经关闭但是里面还有值的通道取值是允许的,可以正常获取到值
  • 从一个已经关闭但是为空的通道取值是允许的,会获取通道类型元素的零值
  • 不可以再次关闭一个已经关闭的通道,会报错
  • 已经关闭的通道无法再次打开

示例

向一个已经关闭的通道发送值

c := make(chan int, 1) close(c) c <- 1   // 报错 

从一个已经关闭但是里面还有值的通道取值

c := make(chan int, 1) c <- 1 close(c) a := <-c fmt.Println(a)  // 输出 1 

从一个已经关闭但是为空的通道取值

c := make(chan int, 1) close(c) a := <-c fmt.Println(a)  // 输出 0  

关闭一个已经关闭的通道

c := make(chan int, 1) close(c) close(c) // 报错: panic: close of closed channel 

单向通道

说明

在函数中使用通道时我们可以限制其为只读通道或者只写通道。

只读通道

func doWork(i <-chan int) {     <-i      // 只能取值     //i <- 1 // 存值操作将不被允许 } 

只写通道

func doWork(i chan <- int) {     i <- 1      // 只能存值     //<-i       // 取值操作将不被允许 } 

案例

channel 通信

使用 channel 实现通信

package main  import (     "fmt"     "sync"     "time" )  var wg sync.WaitGroup  func main() {     fmt.Println("嗨客网(www.haicoder.net)")      c := make(chan int, 1)      c <- 1  // 因为我们定义的通道带有一个缓冲,     // 所以在发布任务之前允许存在最多一个任务投递,也可以写在发布任务之后      // for 循环用于发布任务     for i := 0; i < 2; i++ {         wg.Add(1)         go doWork(c)    // 如果通道现在是空的 goroutine 会等待,         // 如果检测到现在是空的且没有任务投递,就会报错     }      c <- 2  // 多余的任务投递必须在任务发布之后      wg.Wait() }  func doWork(i chan int) {     defer wg.Done()     a := <-i     fmt.Printf("%d 号开始工作了n", a)     time.Sleep(time.Second * 2) // 模拟耗时     fmt.Printf("%d 号结束工作了,输出:%dn", a, a) } 

此时,我们运行程序,控制台输出如下:

Golang channe 你知多少

我们使用了 channel 实现了,收发数据。

channel 通信

使用 channel 实现通信

package main  import (     "fmt"     "sync"     "time" )  var wg sync.WaitGroup  func main() {     fmt.Println("嗨客网(www.haicoder.net)")      c := make(chan int, 1)     wg.Add(1)     go doWork(c)     <-c         // 取值必须在放值之后     wg.Wait() }  func doWork(i chan int) {     defer wg.Done()     fmt.Printf("goroutine 开始工作了n", )     time.Sleep(time.Second * 2) // 模拟耗时     i <- 1     fmt.Printf("goroutine 结束工作了,放入:%dn", 1) } 

此时,我们运行程序,控制台输出如下:

Golang channe 你知多少

我们使用了 channel 实现了,收发数据。

Golang channel 使用总结

在 golang 中 channel 用于 goroutine 之间的通信,channel 是引用类型,需要使用 make 来创建 channel 。在 Golang 中,用通信来共享内存,而不要用共享内存来通信。

原文地址:嗨客网

更多文章,可以关注下方公众号:

Golang channe 你知多少

大佬有話說 (0)

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具