【golang笔记】go_channel实用案例(26)

Page content

这一篇简单的整理了golang channel实用案例 相关的内容。

1.查询1~80000的素数

思路整理

先创建3个管道:
intchan => 启用一个协程往这里添加1~80000的数据
resChan => 启动的n个协程从 intchan读取数据后,计算出的素数往这个管道中添加。
exitChan => 每个协程结束任务,往这个管道中添加是否结束的表示符。 当数据达到启用的协程N个,代表所有的任务都跑完。

代码

package main

import (
 "fmt"
 "time"
)

//给管道写入数据
func pushIntChan(intChan chan int) {
 for i := 1; i <= 80000; i++ {
  intChan <- i
 }
 close(intChan)
}

//计算素数
func calculation(intChan, resChan chan int, exitChan chan bool) {
 for {
  //如果 ok =false 说明管道已没数据,退出循环
  num, ok := <-intChan
  if !ok {
   //退出时给exitChan管道输入一个值,表示我这个协程结束。
   exitChan <- true
   break
  }
  //判断是不是素数的标签
  var flag bool = true
  for i := 2; i < num; i++ {
   if num%i == 0 {
    flag = false
    break
   }
  }
  if flag {
   resChan <- num
  }
 }
}

func main() {
 var aa time.Time = time.Now()
 //要是用的协程数
 var n int = 4
 //创建3个管道
 intChan := make(chan int, 1000)  // 输入数据
 resChan := make(chan int, 10000) // 计算素数结果的管道
 exitChan := make(chan bool, n)   // 判断所有的协程都结束的管道

 //输入数据
 go pushIntChan(intChan)

 //启用协程计算素数
 for i := 0; i < n; i++ {
  go calculation(intChan, resChan, exitChan)
 }

 go func() {
  //等待所有的协程结束
  for i := 0; i < n; i++ {
   <-exitChan
  }
  close(resChan)
  close(exitChan)
 }()
 //关闭管道

 for {
  v, ok := <-resChan
  if !ok {
   break
  }
  fmt.Println(v)
 }

 //这么写速度更快
 //等待所有的协程结束
 // for i := 0; i < n; i++ {
 //  <-exitChan
 // }
 // //关闭管道
 // close(exitChan)
 // close(resChan)

 // fmt.Println(len(resChan))

 // for v := range resChan {
 //  fmt.Println(v)
 // }

 fmt.Println(time.Now().Sub(aa))
}

2.sync.WaitGroup的简单使用

package main

import (
 "fmt"
 "sync"
)

func sender(ch chan int, wg *sync.WaitGroup) {
 for i := 0; i < 10; i++ {
  ch <- i
 }
 close(ch)
 wg.Done()
}
func receiver(ch chan int, wg *sync.WaitGroup) {
 for {
  if val, ok := <-ch; ok {
   fmt.Println(fmt.Sprintf("%d,%s", val, "revevier"))
  } else {
   fmt.Println("quit recevier")
   break
  }
 }
 wg.Done()
}
func receiver2(ch chan int, wg *sync.WaitGroup) {
 for {
  if val, ok := <-ch; ok {
   fmt.Println(fmt.Sprintf("%d,%s", val, "revevier2"))
  } else {
   fmt.Println("quit recevier2")
   break
  }
 }
 wg.Done()
}
func main() {
 ch := make(chan int, 0)
 wg := &sync.WaitGroup{}
 wg.Add(1)
 go sender(ch, wg)
 wg.Add(1)
 go receiver(ch, wg)
 wg.Add(1)
 go receiver2(ch, wg)
 wg.Wait()
}

欢迎大家的意见和交流

email: li_mingxie@163.com