golang常用并发编程的几种模式

一.优胜劣汰模式

场景:执行远程访问,远程服务响应不可靠的时候,同时开启go程,只取最快返回的,可以提高程序性能,但是占用资源会高一些

func job() int{
   rand.Seed(time.Now().Unix())
   ret := rand.Intn(5)
   time.Sleep(time.Second * time.Duration(ret)) // 模拟业务访问延迟
   return ret
}

func main() {
   c := make(chan int)
   for i := 0; i < 5; i++ {
      go func() {
         c <- job()
      }()
   }
   fmt.Printf("最快的用了%d s", <-c)
}

二.扇入和扇出

扇入:多个channel 读取相同数据合并输出到一个总的channel里;
扇出:主要用来收集扇入汇总的数据做进一步处理。

// In  扇入
func in(chs ... <- chan interface{}) <- chan interface{} {
   retChan := make(chan interface{})
   wg := sync.WaitGroup{}
   for _, ch := range chs{
      wg.Add(1)
      go func(ch <- chan interface{}) {
         defer wg.Done()
         // 遍历 ch 会出现阻塞
         for v := range ch{
            retChan <- v
         }
      }(ch)
   }
    // 优雅关闭grouting 
   go func() {
      defer close(retChan)
      wg.Wait()
   }()
   return  retChan
}

// getUser 模拟一个业务函数
func getUser() <- chan interface{}{
   userChan := make(chan interface{})
   go func() {
      defer close(userChan)
      time.Sleep(time.Second * 5) // 模拟业务访问耗时
      userChan <- "User:heihei"  // 整个扇入和扇出环节, 对channel的写入只在该环节
   }()
   return userChan
}

// getGoods 模拟一个业务函数
func getGoods() <- chan interface{}{
   goodsChan := make(chan interface{})
   go func() {
      defer close(goodsChan)
      time.Sleep(time.Second * 2) // 模拟业务访问耗时
      goodsChan <- "goods:haha"  // 整个扇入和扇出环节, 对channel的写入只在该环节
   }()
   return goodsChan
}

func main() {
   ret := in(getUser(), getGoods())
   for v := range ret{
      fmt.Println(v)
   }

三.生产者模式

func Producer(out chan int) {
   defer close(out)
   for i :=0; i < 5; i++ {
      out <- i*2
      time.Sleep(time.Second *2)
   }
}

func Consumer(out chan int)(r chan struct{}){
   r = make(chan struct {})
   go func() {
      defer close(r)
      defer func() {
         r <- struct{}{}
      }()
      for item := range out{    
          fmt.Println(item) // 模拟业务逻辑
       }
   }()
   return r
}
func main() {
   c := make(chan int)
   go Producer(c)
   r := Consumer(c)
   <-r

四.goroutine 并发执行顺序的控制

方式一.通过channel控制
var ch = make(chan struct{}, 1)

func job1() {
   fmt.Println("job1...")
   ch <- struct{}{}
}

func job2() {
   <- ch  // 阻塞等待 job1 执行完成
   fmt.Println("job2...")
}
func do(fns ...func()) *sync.WaitGroup {
   wg := &sync.WaitGroup{}
   for _, fn := range fns{
      wg.Add(1)
      go func(f func()) {
         defer wg.Done()
         f()
      }(fn)
   }
   return  wg
}
func main() {
   wg := do(job1,job2)
   wg.Wait()
}

五、控制协程数量

func myJob() {
   time.Sleep(time.Second * 3)
   fmt.Println(rand.Intn(100))
}

func setPool(ch chan struct{}) {
   for i := 0; i < 5; i++ {
      ch <- struct{}{}
   }
}


func main() {
   // 空struct{} 不占空间
   pool := make(chan struct{}, 5)
   setPool(pool)  // 1.先 set 5个任务到channel中
   wg := sync.WaitGroup{}
   wg.Add(5)  // 2.等待5个任务执行完
   go func() {
      for {
         wg.Wait()  // 5.等待上一组5个任务跑完
         fmt.Println("发放了5个任务...")
         setPool(pool) // 6.再分发5个任务
         wg.Add(5)
      }
   }()
   for {
      <- pool  // 3.通过接收1中set到的任务, 先跑
      go func() {
         defer wg.Done() // 4.每跑完1个任务就通过Done来减1
         myJob()
      }()
   }
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Golang(又称Go)是一种静态类型,编译型,开源的编程语言,它以简洁、高效、并发和可靠著称。学习Golang主要包括以下几个步骤。 1. 学习基本语法:首先,要理解Golang的基本语法,包括变量、函数、数据类型、运算符、流程控制等。可以通过在线教程、书籍或官方文档来学习。 2. 熟悉标准库:Golang提供了丰富的标准库,包括各种常用功能,如字符串处理、文件操作、网络编程等。熟悉标准库可以帮助我们更快地编写高效的代码。 3. 学习并发编程Golang天生支持并发编程,通过goroutine和channel可以实现高效的并发操作。学习并发编程可以帮助解决高并发场景下的问题,提升程序性能。 4. 掌握常用框架和工具:Golang有许多优秀的框架和工具,如Gin、Beego、Echo等。这些框架和工具可以帮助提高开发效率,快速搭建应用。 5. 实践项目:通过实践项目来巩固所学知识,可以选择一些小型的项目开始,逐渐挑战更复杂的项目。通过实践不断提升编程技能和解决问题的能力。 6. 加强算法和数据结构的学习:算法和数据结构是编程的基础,深入学习并理解常见的算法和数据结构是提升编程能力的重要一步。 总结起来,学习Golang的顺序应该是先学习基本语法,然后掌握标准库,学习并发编程,掌握常用框架和工具,实践项目,最后加强算法和数据结构的学习。此外,持续积累编程经验和不断学习新技术也是非常重要的。 ### 回答2: 学习Golang的顺序可以分为四个主要步骤。 1. 学习基本语法和数据类型 首先,要学习Golang的基本语法和数据类型。了解如何声明变量、使用条件语句、循环和函数等基本概念。掌握Golang中的数据类型包括整数、浮点数、字符、字符串、数组、切片、映射、结构体等。理解它们的特点和用法是学习Golang的基础。 2. 掌握面向对象编程 Golang支持面向对象编程,要学习如何使用结构体和方法定义和组织代码。学习如何创建结构体类型和使用方法来处理结构体实例。了解封装、继承和多态的概念,并学会如何在Golang实现它们。 3. 学习并发编程 Golang是为并发编程而生的语言,学习并发编程是使用Golang的重要一步。了解Golang并发原语,例如goroutine和通道。掌握如何创建和管理goroutine,并学会使用通道进行不同goroutine之间的通信和同步。理解并发编程的基本概念和常见问题,例如竞态条件和死锁,并学习如何解决它们。 4. 深入学习标准库和其它常用包 最后,要深入学习Golang的标准库和其它常用包。Golang拥有丰富的标准库,涵盖了许多领域,包括网络编程、文件处理、数据库操作等。学习如何使用标准库中提供的功能来解决实际问题。此外,还可以学习一些常用的第三方库,以扩展Golang的功能和效率。 总结起来,学习Golang的顺序是:基本语法和数据类型 -> 面向对象编程 -> 并发编程 -> 标准库和其它常用包。通过有序的学习,可以逐步掌握Golang的核心概念和技术,为实际项目的开发做好准备。 ### 回答3: 学习Golang的顺序可以分为以下几个步骤: 1. 学习基本语法:首先要了解Golang的基本语法规则,包括变量、常量、数据类型、函数、控制流等。可以通过阅读官方文档、在线教程或者参考书籍来学习。 2. 理解并发编程Golang是以并发为核心设计的编程语言,支持轻量级的线程(Goroutine)和通信(Channel)机制。学习并发编程的原理和技巧,包括Goroutine的创建和调度、Channel的使用、互斥锁和条件变量等。 3. 掌握标准库:Golang提供了丰富的标准库,涵盖了文件处理、网络编程、数据解析、加密解密等各个方面。学习并熟悉标准库的使用,可以提高开发效率和代码质量。 4. 学习常用框架和工具:Golang有许多优秀的第三方框架和工具可供使用,如Web开发框架Gin、数据库ORM框架GORM、测试框架Testify等。选择合适的框架和工具,可以提高开发效率和性能。 5. 实践项目:通过实际项目的练习,将所学知识应用到实际中,加深理解和巩固技能。可以选择一些简单但实用的项目,逐渐挑战更复杂的需求。 6. 阅读优秀的开源代码:阅读和理解一些优秀的开源项目代码,可以提高自己的编程水平和技术见识。可以选择一些知名的开源项目,如Docker、Kubernetes等。 总之,学习Golang需要循序渐进,从基础语法开始,逐步深入学习并发编程、标准库、框架和工具的使用,同时注重实践项目和阅读开源代码。通过不断学习和练习,可以掌握Golang的使用技巧,提升自己的编程能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值