首页 > 编程学习 > golang协程基本开发

文章目录

  • 说明
  • 分享
  • 协程实例
    • 无参协程
    • 带参协程
    • 多个带参协程
  • 总结

说明

golang语言是谷歌发布的近几年比较流行的编译型高级编程语言,语言设计之初把编译与简单作为核心,java程序臃肿内存占用大且必须依赖于jdk(近今年也在尝试编译,个人观点不理想),从这点上看,golang编译后安装包大小和内存占用上有很大优势。
golang推行的协程可以轻松实现上万并发,在高并发小计算场景下有着很好的前景,成功作品Docker可以看出golang潜质,国内部分公司已把它作为招聘选项
本博文介绍协程的基本使用方法

分享

  • 大数据博客列表
  • 开发记录汇总
  • 个人java工具库 项目https://gitee.com/wangzonghui/object-tool
    • 包含json、string、集合、excel、zip压缩、pdf、bytes、http等多种工具,欢迎使用。

协程实例

  • 废话不多说,上代码

无参协程

  • 创建一定数量 无返回 协程,通过sync实现等待所有协程结束
package mainimport ("fmt""sync"
)//待执行的协程函数
func add_num(a, b int, done func()) {//defer 退出前执行标记协程结束方法defer done()c := a + bfmt.Printf("%d + %d = %d\n", a, b, c)
}func main() {//设置协程数量var num int =10//创建并发等待组var wg sync.WaitGroup//设置等待结束的协程数wg.Add(num)for i := 0; i < num; i++ {//创建协程go add_num(i, 1, wg.Done)}//等待所有协程结束wg.Wait()
}

带参协程

  • 通过channel创建数据传入、数据传出、协程结束三个通道实现主程序与协程间通信,创建4个协程,提取1~800000间素数
package mainimport ("fmt""time"
)/*
开启通道+4个协程提取1~800000间的素数
*/
func putData(intChan chan int) {for i := 1; i <= 800000; i++ {intChan <- i}close(intChan)
}func primeNum(intChan chan int, primeChan chan int, exitChan chan bool) {//异常处理 defer + recoverdefer func() {//捕获 test 抛出的 panicif err := recover(); err != nil {fmt.Println("test() 发生错误", err)}}()var flag boolfor {num, ok := <-intChanif !ok {break}flag = true //假设是素数for i := 2; i < num; i++ {if num%i == 0 {flag = false // 不是素数break}}if flag {// 如果是素数就将这个数放到primeChan中primeChan <- num}}fmt.Println("有一个primeNum协程因为取不到数据退出...")// 这里还不能关闭// 向exitChan写入trueexitChan <- true
}func main() {t1 := time.Now()intChan := make(chan int, 1000)primeChan := make(chan int, 2000)// 标识退出的管道exitChan := make(chan bool, 4)// 将管道中的数据存放到切片中var data []int// 开启一个协程,向intChan放入1-8000个数据go putData(intChan)// 开启四个协程,从intChan中取出数据判断是否是素数,并且放到primeChan中for i := 0; i < 4; i++ {go primeNum(intChan, primeChan, exitChan)}// 开启一条协程负责去关闭primeChan协程go func() {for i := 0; i < 4; i++ {<-exitChan}// 当我们从exitChan中取出4个结果,就可以关闭primeChanclose(primeChan)}()// 遍历primeChan,把结果取出来for {val, ok := <-primeChanif !ok {break}// 把结果输出// fmt.Printf("素数 = %d\n", val)data = append(data, val)}t2 := time.Now()//数据长度fmt.Println("len data: ", len(data))//执行时间fmt.Println(t2.Second() - t1.Second())
}

多个带参协程

  • 多协程执行任务时通过select选择channel,提取不同协程之间的数据
package mainimport ("fmt""time"
)func main() {// 使用select 可以解决从管道取数据的阻塞问题// 1、定义一个管道 10个数据intintChan := make(chan int, 10)for i := 0; i < 10; i++ {intChan <- i}// 2、定义一个管道 5个数据stringstrChan := make(chan string, 5)for i := 0; i < 5; i++ {strChan <- "Hello," + fmt.Sprintf(" %d", i)}// 传统的方法在遍历信道时,如果不关闭读取会阻塞而导致 deadLock// 在实际开发中,多协程操作一个管道的时候,不好确定什么时候关闭管道// 使用select可以解决这个问题for {select {case v := <-intChan:fmt.Println("intChan读取的数据--> ", v)time.Sleep(time.Second * 2)case w := <-strChan:fmt.Println("strChan读取到的数据--> ", w)time.Sleep(time.Second * 2)default:fmt.Println("读取不到数据")return}}
}

总结

  • 个人非常喜欢golang语言,编译后安装包非常小,资源占用低,没有java的臃肿,Python的低效运行和依赖,c++的复杂和低效率开发,是做个人工具的最优选择。
  • 新年后第一篇博客,祝大家新年好

本文链接:https://www.ngui.cc/article/show-861350.html
Copyright © 2010-2022 ngui.cc 版权所有 |关于我们| 联系方式| 豫B2-20100000