现在需求是读取一批图片,然后批量上传到七牛云。
现在是第一版,思路就是起5个携程,然后对图片列表进行遍历循环,如果携程数使用超过5个就阻塞代码。
这里用到channel 信号量限流作用,就是往channel 写数据,如果channel 满了,就阻塞channel,直到对向从channel里边
把数据读取了。
const maxGoroutines = 5
guard := make(chan struct{}, maxGoroutines) // 限制并发量
var wg sync.WaitGroup
for _, m := range matches {
if len(m) <= 1 {
continue
}
rawUrl := m[1]
// 取 path(去掉 host,只要路径)
u, er := url.Parse(rawUrl)
var path string
if er == nil {
path = u.Path
} else {
// 如果不是完整 URL,就直接用
if strings.HasPrefix(rawUrl, "/") {
path = rawUrl
} else {
path = "/" + rawUrl
}
}
// 查询 Redis 是否已完成
doneKey := fmt.Sprintf("picrew:done:%d:%s", postId, path)
exists, er := start.RedisClient.Exists(context.Background(), doneKey).Result()
if er != nil {
fmt.Println("Redis 查询失败:", er)
continue
}
if exists > 0 {
//fmt.Printf("文件已存在%s\n", doneKey)
continue // 已完成,跳过
}
wg.Add(1)
guard <- struct{}{} // 占用一个协程名额
// 启动协程处理 URL
go func(url string) {
defer wg.Done()
defer func() { <-guard }() // 释放协程名额
err = picrewService.UpdateQiniu(BaseUrl+url, url)
fmt.Printf("图片地址: %s, 返回值: %v\n", doneKey, err)
if err == nil {
start.RedisClient.Set(context.Background(), doneKey, 1, 0)
}
}(path)
}
wg.Wait()
评论