Go 协程基础:轻松入门并发编程,解析 Goroutines 的奥秘

2023-12-10 03:36

本文主要是介绍Go 协程基础:轻松入门并发编程,解析 Goroutines 的奥秘,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、协程基本使用

1、启动一个协程
  • 主线程中每个100毫秒打印一次,总共打印2次
  • 另外开启一个协程,打印10次
  • 情况一:打印是交替,证明是并行的
  • 情况二:开启的协程打印2次,就退出了(因为主线程退出了)
package mainimport ("fmt""time"
)func test() {for i :=o;i<10;i++ {fmt.PrintIn("test() 你好golang")time.Sleep(time.Millisecond * 100)}
}func main() {go test()    //表示开启一个协程for i:=0;i<2;i++ {fmt.PrintIn("main() 你好golang")time.Sleep(time.Millisecond * 100)}
}
/*
main() 你好golang
test() 你好golang
main() 你好golang
test() 你好golang
test() 你好golang
*/
 2、WaitGroup等待协程执行完毕
  • 主线程退出后所有的协程无论有没有执行完毕都会退出
  • 所以我们在主进程中可以通过WaitGroup等待协程执行完毕
    • sync.WaitGroup内部维护者一个计数器,计数器的值可以增加和减少
    • 例如当我们启动了N个并发任务时,就将计数器值增加N
    • 每个任务完成时通过调用Done()方法将计数器减1
    • 通过调用Wait来等待并发任务执行完,当计数器值为0时,表示所有并发任务已经完成

var wg sync.waitGroup      //第一步:定义一个计数器

wg.Add(1)                        //第二步:开启一个协程计数器+1

wg.Done()                        //第三步:协程执行完毕,计数器-1

wg.Wait()                        //第四步:计数器为0时退出

package mainimport ("fmt""sync""time"
)var wg sync.WaitGroup         //第一步:定义一个计数器func  test1() {for i :=0;i<10;i++ {fmt.PrintIn("test1() 你好golang",i)time.Sleep(time.Millisecond * 100)}wg.Done()    //协程计数器-1    //第三步:协程执行玩不,计数器-1
}func  test2() {for i :=0;i<2;i++ {fmt.PrintIn("test2() 你好golang",i)time.Sleep(time.Millisecond * 100)}wg.Done()    //协程计数器-1   
}func main() {wg.Add(1)    //协程计数器+1     第二不:开启一个协程计数器+1go test1()    //表示开启一个协程wg.Add(1)    //协程计数器+1go test2()    //表示开启一个协程wg.Wait()    //等待协程执行完毕... 第四步:计数器为0时退出fmt.PrintIn("主线程退出...")}/*
test2() 你好golang- 0
test1() 你好golang- 0
.....
test1() 你好golang- 8
test1() 你好golang- 9
主线程退出...
*/

 二、多协程案例

1、开启多个协程
  • 在Go语言中实现并发就是这样简单,我们还可以启动多个goroutine
  • 这里使用了sync.WaitGroup来实现等待goroutine执行完毕
  • 多次执行上面的代码,会发现每次打印的数字的顺序都不一致
  • 这是因为10个goroutine是并发执行的,而goroutine的调度是随机的
package mainimport ("fmt""sync"
)var wg sync.WaitGroupfunc hello(i int){defer wg.Done()    //goroutine结束就登记-1fmt.PrintIn("Hello Goroutine!",i)
}func main() {for i :=0;i<10;i++ {wg.Add(1)    //启动一个goroutine就登记+1go hello(i)}wg.Wait()    //等待所有登记的goroutine都结束
}
2、多协程统计素数
  • 需求:要统计1-120000的数字中哪些是素数?goroutine for循环实现
  • 协程 统计 1-30000
  • 协程 统计 30001-60000
  •  协程 统计 60001-90000

  • 协程 统计 90001-120000

  • start:(n-1)*30000+1 end:n*30000

package main
import ("fmt""sync""time"
)
var wg sync.WaitGroupfunc test(n int) {for num := (n-1)*30000 + 1; num < n*30000; num++ {if num > 1 {var flag = truefor i := 2; i < num; i++ {if num%i == 0 {flag = falsebreak}}if flag {fmt.Println(num, "是素数")}}}wg.Done()
}func main() {start := time.Now().Unix()for i := 1; i <= 4; i++ {wg.Add(1)go test(i)}wg.Wait()fmt.Println("执行完毕")end := time.Now().Unix()fmt.Println(end - start) //1毫秒
}

这篇关于Go 协程基础:轻松入门并发编程,解析 Goroutines 的奥秘的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/475916

相关文章

深入理解Go语言中二维切片的使用

《深入理解Go语言中二维切片的使用》本文深入讲解了Go语言中二维切片的概念与应用,用于表示矩阵、表格等二维数据结构,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录引言二维切片的基本概念定义创建二维切片二维切片的操作访问元素修改元素遍历二维切片二维切片的动态调整追加行动态

PostgreSQL的扩展dict_int应用案例解析

《PostgreSQL的扩展dict_int应用案例解析》dict_int扩展为PostgreSQL提供了专业的整数文本处理能力,特别适合需要精确处理数字内容的搜索场景,本文给大家介绍PostgreS... 目录PostgreSQL的扩展dict_int一、扩展概述二、核心功能三、安装与启用四、字典配置方法

go中的时间处理过程

《go中的时间处理过程》:本文主要介绍go中的时间处理过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1 获取当前时间2 获取当前时间戳3 获取当前时间的字符串格式4 相互转化4.1 时间戳转时间字符串 (int64 > string)4.2 时间字符串转时间

Go语言中make和new的区别及说明

《Go语言中make和new的区别及说明》:本文主要介绍Go语言中make和new的区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1 概述2 new 函数2.1 功能2.2 语法2.3 初始化案例3 make 函数3.1 功能3.2 语法3.3 初始化

从入门到精通MySQL联合查询

《从入门到精通MySQL联合查询》:本文主要介绍从入门到精通MySQL联合查询,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下... 目录摘要1. 多表联合查询时mysql内部原理2. 内连接3. 外连接4. 自连接5. 子查询6. 合并查询7. 插入查询结果摘要前面我们学习了数据库设计时要满

深度解析Java DTO(最新推荐)

《深度解析JavaDTO(最新推荐)》DTO(DataTransferObject)是一种用于在不同层(如Controller层、Service层)之间传输数据的对象设计模式,其核心目的是封装数据,... 目录一、什么是DTO?DTO的核心特点:二、为什么需要DTO?(对比Entity)三、实际应用场景解析

深度解析Java项目中包和包之间的联系

《深度解析Java项目中包和包之间的联系》文章浏览阅读850次,点赞13次,收藏8次。本文详细介绍了Java分层架构中的几个关键包:DTO、Controller、Service和Mapper。_jav... 目录前言一、各大包1.DTO1.1、DTO的核心用途1.2. DTO与实体类(Entity)的区别1

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

从入门到精通C++11 <chrono> 库特性

《从入门到精通C++11<chrono>库特性》chrono库是C++11中一个非常强大和实用的库,它为时间处理提供了丰富的功能和类型安全的接口,通过本文的介绍,我们了解了chrono库的基本概念... 目录一、引言1.1 为什么需要<chrono>库1.2<chrono>库的基本概念二、时间段(Durat

Go语言中nil判断的注意事项(最新推荐)

《Go语言中nil判断的注意事项(最新推荐)》本文给大家介绍Go语言中nil判断的注意事项,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1.接口变量的特殊行为2.nil的合法类型3.nil值的实用行为4.自定义类型与nil5.反射判断nil6.函数返回的