Go 语言学习之 goroutine 和 channel

简介: Go 语言学习之 goroutine 和 channel

01

goroutine


当一个 go 程序运行时,调用 main 函数入口的 goroutine 是主 goroutine,我们还可以使用关键字 go 创建新的 goroutine。在 Go 语言中,创建 goroutine 的语法很简单,只需要在函数或方法调用前加上 go 关键字。


02

channel


channel 是可以让一个 goroutine 发送特定的值到另一个 goroutine 的通信机制。Go 官方鼓励使用 CSP 并发编程风格,以通信代替内存共享,实现并发安全。


与 map 类似,channel 也是使用内置函数 make 创建。channel 是引用类型,它的零值是 nil,channel 可以和 nil 进行比较,相同类型的 channel 可以使用 “==” 符号进行比较。


使用内置函数 make 创建 channel 时,有两个参数,第一个参数是元素类型,第二个可选参数是 channel 的容量。不设置 channel 容量称为无缓冲 channel,设置 channel 容量称为缓冲 channel。无缓冲 channel 是一种阻塞的同步 channel。内置函数 cap 可以获取缓冲 channel 的容量,内置函数 len 可以获取缓冲 channel 的元素个数。


03

channel 操作


channel 操作有三种,分别是 send、receive 和 close。send 操作可以从一个执行的 goroutine 传输一个值到另一个执行 receive 操作的 goroutine。


send 操作和 receive 操作都使用 “<-” 操作符,在 send 语句中,channel 和值分别在操作符左右两边,在 receive 语句中,操作符放在 channel 操作数的前面。


close 操作通过设置一个标志位来表示当前值已经 send 完毕,channel 不会再被 send 值了,close 操作后的 send 操作将导致宕机。在一个已经执行 close 操作的 channel 上执行 receive 操作,将获取这个 channel 上所有已经 send 的值,直到 channel 为空。


缓冲 channel 的 send 操作在队列的尾部插入一个元素,receive 操作在队列的头部移除一个元素。如果缓冲 channel 容量占满,send 操作会阻塞所在的 goroutine,直到另一个 goroutine 对它执行 receive 操作来腾出可用空间。如果缓冲 channel 是空的,receive 操作的 goroutine 阻塞,直到另一个 goroutine 在这个缓冲 channel 上 send 数据。


需要注意的是,如果在同一个缓冲 channel 上执行 send 操作和 receive 操作,是将缓冲 channel 错误地作为队列使用了。在实际项目开发中,send 操作和 receive 操作是由不同的 goroutine 执行的。


无缓冲 channel 的每一次 send 操作都对应一次 receive 操作,实现强同步。缓冲 channel 的 send 操作和 receive 操作是解耦的。我们如果事先可以知道需要 send 的值的数量上限,可以创建一个容量是使用上限的缓冲 channel,在 receive 第一个值前就完成了所有的 send 操作。


使用缓冲 channel,需要注意 send 操作和 receive 操作的 goroutine 的执行效率,否则会影响性能。


04

select 多路复用


select 语句类似 switch 语句,有至少一个 case 分支,和一个可选的默认分支 default。每一个 case 分支指定一次通信(在一些 channel 上执行 send 操作或 receive 操作)和关联的一段代码块。


select 一直处于等待状态,直到一次通信可以符合条件执行某一个或多个 case 分支的代码块,然后 select 执行这次通信,并执行对应的 case 分支,其他的通信将不会发生,select 如果没有可以符合条件执行的 case 分支,它将永远处于等待状态。select 如果同时符合多个 case 分支执行,select 将随机选择一个 case 分支执行。


select  如果有可选默认分支 default,在没有通信可以符合条件执行某一个 case 分支时,它将执行默认分支 default 的代码块。





目录
相关文章
|
6天前
|
存储 JSON 监控
Viper,一个Go语言配置管理神器!
Viper 是一个功能强大的 Go 语言配置管理库,支持从多种来源读取配置,包括文件、环境变量、远程配置中心等。本文详细介绍了 Viper 的核心特性和使用方法,包括从本地 YAML 文件和 Consul 远程配置中心读取配置的示例。Viper 的多来源配置、动态配置和轻松集成特性使其成为管理复杂应用配置的理想选择。
23 2
|
4天前
|
Go 索引
go语言中的循环语句
【11月更文挑战第4天】
13 2
|
4天前
|
Go C++
go语言中的条件语句
【11月更文挑战第4天】
16 2
|
7天前
|
监控 Go API
Go语言在微服务架构中的应用实践
在微服务架构的浪潮中,Go语言以其简洁、高效和并发处理能力脱颖而出,成为构建微服务的理想选择。本文将探讨Go语言在微服务架构中的应用实践,包括Go语言的特性如何适应微服务架构的需求,以及在实际开发中如何利用Go语言的特性来提高服务的性能和可维护性。我们将通过一个具体的案例分析,展示Go语言在微服务开发中的优势,并讨论在实际应用中可能遇到的挑战和解决方案。
|
4天前
|
Go
go语言中的 跳转语句
【11月更文挑战第4天】
13 4
|
4天前
|
JSON 安全 Go
Go语言中使用JWT鉴权、Token刷新完整示例,拿去直接用!
本文介绍了如何在 Go 语言中使用 Gin 框架实现 JWT 用户认证和安全保护。JWT(JSON Web Token)是一种轻量、高效的认证与授权解决方案,特别适合微服务架构。文章详细讲解了 JWT 的基本概念、结构以及如何在 Gin 中生成、解析和刷新 JWT。通过示例代码,展示了如何在实际项目中应用 JWT,确保用户身份验证和数据安全。完整代码可在 GitHub 仓库中查看。
18 1
|
8天前
|
Go 数据处理 API
Go语言在微服务架构中的应用与优势
本文摘要采用问答形式,以期提供更直接的信息获取方式。 Q1: 为什么选择Go语言进行微服务开发? A1: Go语言的并发模型、简洁的语法和高效的编译速度使其成为微服务架构的理想选择。 Q2: Go语言在微服务架构中有哪些优势? A2: 主要优势包括高性能、高并发处理能力、简洁的代码和强大的标准库。 Q3: 文章将如何展示Go语言在微服务中的应用? A3: 通过对比其他语言和展示Go语言在实际项目中的应用案例,来说明其在微服务架构中的优势。
|
8天前
|
Go 数据处理 调度
探索Go语言的并发模型:Goroutines与Channels的协同工作
在现代编程语言中,Go语言以其独特的并发模型脱颖而出。本文将深入探讨Go语言中的Goroutines和Channels,这两种机制如何协同工作以实现高效的并发处理。我们将通过实际代码示例,展示如何在Go程序中创建和管理Goroutines,以及如何使用Channels进行Goroutines之间的通信。此外,本文还将讨论在使用这些并发工具时可能遇到的常见问题及其解决方案,旨在为Go语言开发者提供一个全面的并发编程指南。
|
6天前
|
Go 调度 开发者
探索Go语言中的并发模式:goroutine与channel
在本文中,我们将深入探讨Go语言中的核心并发特性——goroutine和channel。不同于传统的并发模型,Go语言的并发机制以其简洁性和高效性著称。本文将通过实际代码示例,展示如何利用goroutine实现轻量级的并发执行,以及如何通过channel安全地在goroutine之间传递数据。摘要部分将概述这些概念,并提示读者本文将提供哪些具体的技术洞见。
|
Go
Go简单的Goroutine示例
最简单的,接下来,会是竞争,加锁。。。 package main import ( "fmt" "runtime" "sync" ) var wg sync.WaitGroup func main() { runtime.
1092 0