您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Go语言

Go语言之通道篇

时间:2023-08-27 14:52:58  来源:  作者:程序员技术成长之路

通道的定义

    通道是Go用于协程之间进行通讯的工具。Go的通道(channel)是一种特殊的类型,可以让你发送类型化的数据,在两个Go协程(goroutine)之间进行同步、数据传递。它是并发安全的,也就是说在多个协程之间传递对共享数据的所有权,避免协程之间的数据竞争。因此,通常将通道用于在两个协程之间传递数据。

    在Go语言中,通道可以传递任何类型的值。你可以将它们视为管道或队列,通过它们可以发送或接收值。这些值都有一个特定的类型,例如int或string,你也可以通过通道发送或接收自定义的数据类型,比如结构体、数组、切片、映射等,甚至是其他通道。

但需要注意的是,通道在声明时需要为其指定元素类型,一个通道只能传输一种类型的数据,不同类型的数据需要通过不同的通道来传输。例如,使用chan int声明的通道只能传输整型数据,使用chan string声明的通道只能传输字符串。

示例

  1. 单向通道:

package mAIn
import "fmt"
func message(passMsg chan<- string){    passMsg <- "A message from message function"}
func main(){    defaultMessage := make(chan string)    go message(defaultMessage)    fmt.Println(<-defaultMessage)}

在此示例中,我们创建一个发送给主功能的消息函数。我们通过 "chan<-" 关键字来确保这个频道仅用于发送消息。

 2、双向通道

package main
import "fmt"
func message(passMsg chan string){    passMsg <- "A message from message function"    msg := <- passMsg    fmt.Println(msg)}
func main(){    defaultMessage := make(chan string)    go message(defaultMessage)    defaultMessage <- "A message from main function"}

        在此示例中,我们创建一个从主函数发送并接收到消息函数的消息。这是一个双向通道,我们通过 "chan" 关键字来建立。在主函数,我们给通道发送消息,在消息函数中,我们收到主函数的消息并在该函数中发送一个新消息。

3、缓冲的通道:

package main
import "fmt"
func main() {    ch := make(chan int, 2)    ch <- 1    ch <- 2    fmt.Println(<-ch)    fmt.Println(<-ch)}

在此示例中,我们创建了一个带缓冲的通道,该通道可以存储两个整数值。我们向通道发送两个值,然后接收这两个值,不会阻塞,因为通道已经有缓冲区存储这两个值。

4、关闭通道和检测通道是否关闭

ch := make(chan int)close(ch)
//你可以通过让接收表达式返回一个二参数来检查通道是否被关闭。如果ok为false,那说明通道已经没有数据可以接收,并且已经被关闭。例如:v, ok := <-ch
package main
import (  "fmt")
func main() {  ch := make(chan int, 2)
  // 发送方  go func() {    for i := 0; i < 10; i++ {      ch <- i    }    close(ch) // 不再需要发送数据,关闭channel  }()
  // 接收方  for {    if v, ok := <-ch; ok {      fmt.Println(v)    } else {      fmt.Println("Channel closed!")      break    }  }}

在这个示例中,通过检查 ok 的值来判断通道是否已经被关闭。一旦检测到通道已经被关闭,就 break 循环,终止读取。

5、使用通道来进行锁的竞争,避免并发

package main
import (  "fmt"  "sync")
var counter = 0
func increment(wg *sync.WaitGroup, ch chan bool) {  ch <- true  counter++  <-ch  wg.Done()}
func main() {  var wg sync.WaitGroup  ch := make(chan bool, 1)
  for i := 0; i < 1000; i++ {    wg.Add(1)    go increment(&wg, ch)  }  wg.Wait()
  fmt.Println("Final Counter:", counter)}

在这个示例中,我们有一个名为"counter"的全局变量,我们希望在多个goroutine中并发地递增这个变量。为了避免数据竞争,我们使用了一个缓冲区为1的通道。

在"increment"函数中,我们先发送一个值到通道,然后对"counter"进行递增。当递增完毕后,我们从通道接收值,这会释放通道缓冲区的空间,以便其他的goroutine可以发送值到通道。

因此,由于通道的缓冲区大小为1,只有一个goroutine能够对"counter"进行递增。这就实现了对"counter"访问的互斥,有效避免了数据竞争。

 

6、go-range读取通道的值

package main
import (  "fmt"  "time")
func produce(c chan int) {  for i := 0; i < 10; i++ {    c <- i    fmt.Println("send:", i)    time.Sleep(time.Millisecond * 500)  }  close(c)}
func main() {  c := make(chan int, 5)  go produce(c)
  // 使用 'range'循环读取通道数据  for v := range c {    fmt.Println("receive:", v)  }}

在此示例中,produce函数将数字0到9发送到通道,然后关闭通道。main函数中,使用for v := range c循环读取通道数据,直到通道被关闭。每次从通道中读取数据并打印,只有当通道中没有数据并且通道被关闭时,才会退出循环。这是通过内建的close函数把关闭信息传递给接收方实现的。



Tags:Go语言   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
宝藏级Go语言开源项目——教你自己动手开发互联网搜索引擎
DIYSearchEngine 是一个能够高速采集海量互联网数据的开源搜索引擎,采用 Go 语言开发。Github 地址:https://github.com/johnlui/DIYSearchEngine运行方法首先,给自己准备一杯...【详细内容】
2024-03-12  Search: Go语言  点击:(18)  评论:(0)  加入收藏
你是否想知道如何应对高并发?Go语言为你提供了答案!
并发编程是当前软件领域中不可忽视的一个关键概念。随着CPU等硬件的不断发展,我们都渴望让我们的程序运行速度更快、更快。而Go语言在语言层面天生支持并发,充分利用现代CPU的...【详细内容】
2023-12-29  Search: Go语言  点击:(107)  评论:(0)  加入收藏
Go语言实现GoF设计模式:适配器模式
简介适配器模式(Adapter)是最常用的结构型模式之一,在现实生活中,适配器模式也是处处可见,比如电源插头转换器,它可以让英式的插头工作在中式的插座上。GoF 对它的定义如下:Convert...【详细内容】
2023-12-12  Search: Go语言  点击:(207)  评论:(0)  加入收藏
Go语言字符串拼接方式与性能比较,分析过没?
在Go语言中,字符串拼接性能是相当高效的,主要原因有两点:一是字符串在Go中是不可变的(immutable),二是Go语言提供了strings.Builder类型来高效处理字符串拼接。1. 字符串是不可变...【详细内容】
2023-12-11  Search: Go语言  点击:(229)  评论:(0)  加入收藏
一篇学会AI与Go语言无缝对接
在当今应用开发领域,类似OpenAI API等生成式AI技术的蓬勃发展正在彻底改变着应用开发的格局。Python和JavaScript等语言已经拥有丰富的资源来支持这些技术,其中LangChain就是...【详细内容】
2023-12-04  Search: Go语言  点击:(141)  评论:(0)  加入收藏
20小时快速入门Go语言
Go语言是由Google开发的一种高效、简洁和并发性强的编程语言,其设计目标是使得程序员能够更加容易地创建可靠、高效的软件。尽管Go语言的语法相对其他编程语言来说可能更加陌...【详细内容】
2023-12-03  Search: Go语言  点击:(154)  评论:(0)  加入收藏
十个令人惊叹的Go语言技巧,让你的代码更加优雅
在开发生产项目的过程中,我注意到经常会发现自己在重复编写代码,使用某些技巧时没有意识到,直到后来回顾工作时才意识到。为了解决这个问题,我开发了一种解决方案,对我来说非常有...【详细内容】
2023-11-20  Search: Go语言  点击:(172)  评论:(0)  加入收藏
Go语言Context应用全攻略:异步编程利器
概述在 Go 语言中,Context(上下文)是一个非常重要的概念,特别是在处理请求时。允许在请求的整个生命周期内传递数据、控制请求的取消、处理超时等。本文将介绍 Go 语言中 Contex...【详细内容】
2023-11-06  Search: Go语言  点击:(304)  评论:(0)  加入收藏
Go语言高级特性:Context深入解读
概述在 Go 语言中,context(上下文)是一个非常重要的概念。它主要用于在多个 goroutine 之间传递请求特定任务的截止日期、取消信号以及其他请求范围的值。3. Context 的取消与...【详细内容】
2023-11-01  Search: Go语言  点击:(232)  评论:(0)  加入收藏
Go语言中如何实现JWT
什么JWTJWT(JSON Web Token)是一种开放标准(RFC 7519),定义了一种在各方之间安全传输信息的简洁方式。这些信息可以被验证和信任,因为它们是数字签名的。JWT由三部分组成,用.分隔。...【详细内容】
2023-09-11  Search: Go语言  点击:(250)  评论:(0)  加入收藏
▌简易百科推荐
宝藏级Go语言开源项目——教你自己动手开发互联网搜索引擎
DIYSearchEngine 是一个能够高速采集海量互联网数据的开源搜索引擎,采用 Go 语言开发。Github 地址:https://github.com/johnlui/DIYSearchEngine运行方法首先,给自己准备一杯...【详细内容】
2024-03-12  OSC开源社区    Tags:Go语言   点击:(18)  评论:(0)  加入收藏
Go Gin框架实现优雅地重启和停止
在Web应用程序中,有时候我们需要重启或停止服务器,无论是因为更新代码还是进行例行维护。在这种情景下,我们需要保证应用程序的可用性和数据的一致性。这就需要优雅地关闭和重...【详细内容】
2024-01-30  源自开发者  微信公众号  Tags:Go   点击:(67)  评论:(0)  加入收藏
如何让Go程序以后台进程或daemon方式运行
本文探讨了如何通过Go代码实现在后台运行的程序。最近我用Go语言开发了一个WebSocket服务,我希望它能在后台运行,并在异常退出时自动重新启动。我的整体思路是将程序转为后台...【详细内容】
2024-01-26  Go语言圈  微信公众号  Tags:Go程序   点击:(60)  评论:(0)  加入收藏
深入Go底层原理,重写Redis中间件实战
Go语言以其简洁、高效和并发性能而闻名,深入了解其底层原理可以帮助我们更好地利用其优势。在本文中,我们将探讨如何深入Go底层原理,以及如何利用这些知识重新实现一个简单的Re...【详细内容】
2024-01-25  547蓝色星球    Tags:Go   点击:(66)  评论:(0)  加入收藏
Go 内存优化与垃圾收集
Go提供了自动化的内存管理机制,但在某些情况下需要更精细的微调从而避免发生OOM错误。本文将讨论Go的垃圾收集器、应用程序内存优化以及如何防止OOM(Out-Of-Memory)错误。Go...【详细内容】
2024-01-15  DeepNoMind  微信公众号  Tags:Go   点击:(61)  评论:(0)  加入收藏
Go函数指针是如何让你的程序变慢的?
导读Go 语言的常规优化手段无需赘述,相信大家也能找到大量的经典教程。但基于 Go 的函数值问题,业界还没有太多深度讨论的内容分享。本文作者根据自己对 Go 代码的使用与调优...【详细内容】
2024-01-15  腾讯云开发者  微信公众号  Tags:Go函数   点击:(86)  评论:(0)  加入收藏
Go编程中调用外部命令的几种场景
在很多场合, 使用Go语言需要调用外部命令来完成一些特定的任务, 例如: 使用Go语言调用Linux命令来获取执行的结果,又或者调用第三方程序执行来完成额外的任务。在go的标准库...【详细内容】
2024-01-09  suntiger    Tags:Go编程   点击:(101)  评论:(0)  加入收藏
Go 语言不支持并发读写 Map,为什么?
Go语言的map类型不支持并发读写的主要原因是并发读写会导致数据竞态(data race),这意味着多个 goroutine 可能同时访问并修改同一个 map,从而引发不确定的结果。在Go语言的设计...【详细内容】
2024-01-05  Go语言圈  微信公众号  Tags:Go 语言   点击:(77)  评论:(0)  加入收藏
Go微服务入门到容器化实践
Go微服务入门到容器化实践Go 是一门高效、现代化、快速增长的编程语言,非常适合构建 Web 应用程序。而 Docker 是一种轻量级的容器化技术,能够使得您的应用程序在任何地方运行...【详细内容】
2024-01-01  大雷家吃饭    Tags:Go微服务   点击:(62)  评论:(0)  加入收藏
你是否想知道如何应对高并发?Go语言为你提供了答案!
并发编程是当前软件领域中不可忽视的一个关键概念。随着CPU等硬件的不断发展,我们都渴望让我们的程序运行速度更快、更快。而Go语言在语言层面天生支持并发,充分利用现代CPU的...【详细内容】
2023-12-29  灵墨AI探索室  微信公众号  Tags:Go语言   点击:(107)  评论:(0)  加入收藏
站内最新
站内热门
站内头条