冀教网 - 河北教师网站 - 专注于冀教版课本资源

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 338|回复: 0

24. 理解 Go 语言中的协程:goroutine

[复制链接]

4万

主题

4万

帖子

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
124999
发表于 2020-6-1 09:06 | 显示全部楼层 |阅读模式
Hi,大家好,我是明哥。
在自己学习 Golang 的这段时间里,我写了详细的学习笔记放在我的个人微信公众号 《Go编程时光》,对于 Go 语言,我也算是个初学者,因此写的东西应该会比较适合刚接触的同学,如果你也是刚学习 Go 语言,不防关注一下,一起学习,一起成长。
我的在线博客:http://golang.iswbm.com
我的 Github:github.com/iswbm/GolangCodingTime
说到Go语言,很多没接触过它的人,对它的第一印象,一定是它从语言层面天生支持并发,非常方便,让开发者能快速写出高性能且易于理解的程序。
在 Python (为Py为例,主要是我比较熟悉,其他主流编程语言也类似)中,并发编程的门槛并不低,你要学习多进程,多线程,还要掌握各种支持并发的库 asyncio,aiohttp 等,同时你还要清楚它们之间的区别及优缺点,懂得在不同的场景选择不同的并发模式。
而 Golang 作为一门现代化的编程语言,它不需要你直面这些复杂的问题。在 Golang 里,你不需要学习如何创建进程池/线程池,也不需要知道什么情况下使用多线程,什么时候使用多进程。因为你没得选,也不需要选,它原生提供的 goroutine (也即协程)已经足够优秀,能够自动帮你处理好所有的事情,而你要做的只是执行它,就这么简单。
一个 goroutine 本身就是一个函数,当你直接调用时,它就是一个普通函数,如果你在调用前加一个关键字 go ,那你就开启了一个 goroutine。
  1. // 执行一个函数func()// 开启一个协程执行这个函数go func()
复制代码
1. 协程的初步使用

一个 Go 程序的入口通常是 main 函数,程序启动后,main 函数最先运行,我们称之为 main goroutine。
在 main 中或者其下调用的代码中才可以使用 go + func() 的方法来启动协程。
main 的地位相当于主线程,当 main 函数执行完成后,这个线程也就终结了,其下的运行着的所有协程也不管代码是不是还在跑,也得乖乖退出。
因此如下这段代码运行完,只会输出  hello, world ,而不会输出hello, go(因为协程的创建需要时间,当 hello, world打印后,协程还没来得及并执行)
  1. import "fmt"func mytest() {        fmt.Println("hello, go")}func main() {    // 启动一个协程        go mytest()        fmt.Println("hello, world")}
复制代码
对于刚学习Go的协程同学来说,可以使用 time.Sleep 来使 main 阻塞,使其他协程能够有机会运行完全,但你要注意的是,这并不是推荐的方式(后续我们会学习其他更优雅的方式)。
当我在代码中加入一行 time.Sleep 输出就符合预期了。
  1. import (        "fmt"        "time")func mytest() {        fmt.Println("hello, go")}func main() {        go mytest()        fmt.Println("hello, world")        time.Sleep(time.Second)}
复制代码
输出如下
  1. hello, worldhello, go
复制代码
2. 多个协程的效果

为了让你看到并发的效果,这里举个最简单的例子
  1. import (        "fmt"        "time")func mygo(name string) {        for i := 0; i < 10; i++ {                fmt.Printf("In goroutine %s\n", name)        // 为了避免第一个协程执行过快,观察不到并发的效果,加个休眠                time.Sleep(10 * time.Millisecond)         }}func main() {        go mygo("协程1号") // 第一个协程        go mygo("协程2号") // 第二个协程        time.Sleep(time.Second)}
复制代码
输出如下,可以观察到两个协程就如两个线程一样,并发执行
  1. In goroutine 协程2号In goroutine 协程1号In goroutine 协程1号In goroutine 协程2号In goroutine 协程2号In goroutine 协程1号In goroutine 协程1号In goroutine 协程2号In goroutine 协程1号In goroutine 协程2号In goroutine 协程1号In goroutine 协程2号In goroutine 协程1号In goroutine 协程2号In goroutine 协程1号In goroutine 协程2号In goroutine 协程1号In goroutine 协程2号In goroutine 协程1号In goroutine 协程2号
复制代码
通过以上简单的例子,是不是折服于Go的这种强大的并发特性,将同步代码转为异步代码,真的只要一个关键字就可以了,也不需要使用其他库,简单方便。
本篇只介绍了协程的简单使用,真正的并发程序还是要结合 信道 (channel)来实现。关于信道的内容,将在下一篇文章中介绍。
系列导读
01. 开发环境的搭建(Goland & VS Code)
02. 学习五种变量创建的方法
03. 详解数据类型:****整形与浮点型
04. 详解数据类型:byte、rune与string
05. 详解数据类型:数组与切片
06. 详解数据类型:字典与布尔类型
07. 详解数据类型:指针
08. 面向对象编程:结构体与继承
09. 一篇文章理解 Go 里的函数
10. Go语言流程控制:if-else 条件语句
11. Go语言流程控制:switch-case 选择语句
12. Go语言流程控制:for 循环语句
13. Go语言流程控制:goto 无条件跳转
14. Go语言流程控制:defer 延迟调用
15. 面向对象编程:接口与多态
16. 关键字:make 和 new 的区别?
17. 一篇文章理解 Go 里的语句块与作用域
18. 学习 Go 协程:goroutine
19. 学习 Go 协程:详解信道/通道
20. 几个信道死锁经典错误案例详解
21. 学习 Go 协程:WaitGroup
22. 学习 Go 协程:互斥锁和读写锁
23. Go 里的异常处理:panic 和 recover
24. 超详细解读 Go Modules 前世今生及入门使用
25. Go 语言中关于包导入必学的 8 个知识点
26. 如何开源自己写的模块给别人用?
27. 说说 Go 语言中的类型断言?
28. 这五点带你理解Go语言的select用法
我的关键词 24. 理解 Go 语言中的协程:goroutine  新闻资讯 1147362-20200601081319879-790451869


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|冀教网 - 河北教师网站 - 专注于冀教版课本资源  

GMT+8, 2020-7-4 23:49 , Processed in 0.332717 second(s), 30 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表