liwl
2023-10-24 16:35 deepin
老哥会说话,但是我不会,哈哈哈
Reply Like 2 View the author
老哥会说话,但是我不会,哈哈哈
package chang
import (
"fmt"
"sync"
"time"
)
func mission(index int, msg chan string, limit chan struct{}, wg *sync.WaitGroup) {
defer wg.Done()
// 这是一个长时间任务
for i := 0; i < 10; i++ {
fmt.Printf("这是第%d个协程的第%d次响应\n", index+1, i)
time.Sleep(300 * time.Millisecond)
}
//实际上msg需要传输经过函数处理的内容
msg <- fmt.Sprintf("这是第%d个协程\n", index)
<-limit
fmt.Printf("从通道中释放一个空结构体\n")
}
func master() {
limit := make(chan struct{}, 5)
msg := make(chan string, 50)
var wg sync.WaitGroup
for i := 0; i < 50; i++ {
limit <- struct{}{}
wg.Add(1)
go mission(i, msg, limit, &wg)
}
go func() {
wg.Wait()
close(msg)
}()
//用来保存从所有通道获取的结果
var finally []string
for data := range msg {
finally = append(finally, data)
}
fmt.Printf("finally is %v\ntype is %T\n", finally, finally)
}
楼上的老哥已经提供了实现代码。我这里贴下怎么在for+select避免goto的使用
//用来保存从所有通道获取的结果
var loop = true
var finally []string
for loop {
select {
case data := <-msg:
finally = append(finally, data)
case <-time.After(5 * time.Second):
fmt.Println("Timeout: No data received,after 3 second")
loop = false
}
}
另外你的这个场景最好不要用time.After,因为这样写每次循环都会创建出一个chan,函数注释里面有写
// After waits for the duration to elapse and then sends the current time
// on the returned channel.
// It is equivalent to NewTimer(d).C.
// The underlying Timer is not recovered by the garbage collector
// until the timer fires. If efficiency is a concern, use NewTimer
// instead and call Timer.Stop if the timer is no longer needed.
提供个思路,使用一个 channel 控制并发数量(简单协程池),使用 for range 遍历 msg channel,协程池为空时可判定为结束全部任务,关闭 msg channel,for range 也会立即结束。
使用 sync.WaitGroup
可能会产生不可控的大量的协程,不如用协池程管理。
Popular Ranking
ChangePopular Events
More
我有一个需求
遍历一个结构体切片
其中每一个元素起一个协程,用来处理数据,并通过通道返回给主协程
已经使用了空结构体控制了协程的并发数量
希望老哥们指点迷津
我愿意为了一个优秀的解决方案付费