欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

go高并發(fā)時append出錯怎么解決

今天小編給大家分享一下go高并發(fā)時append出錯怎么解決的相關知識點,內(nèi)容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

成都網(wǎng)絡公司-成都網(wǎng)站建設公司創(chuàng)新互聯(lián)公司10余年經(jīng)驗成就非凡,專業(yè)從事成都網(wǎng)站制作、網(wǎng)站設計、外貿(mào)網(wǎng)站建設,成都網(wǎng)頁設計,成都網(wǎng)頁制作,軟文平臺1元廣告等。10余年來已成功提供全面的成都網(wǎng)站建設方案,打造行業(yè)特色的成都網(wǎng)站建設案例,建站熱線:13518219792,我們期待您的來電!

背景

在實現(xiàn)圖片轉(zhuǎn)碼的需求時,需要支持最大 500 個圖片下載后轉(zhuǎn)換格式;

如果是一個一個下載后轉(zhuǎn)碼,耗時太長,需要使用 goroutine 實現(xiàn) 500 個圖片并發(fā)下載后,并發(fā)轉(zhuǎn)碼;

但自測過程中發(fā)現(xiàn),會偶現(xiàn)下載后只轉(zhuǎn)換了 499 個圖片或更少的情況(全部下載、轉(zhuǎn)碼成功的條件下);

然后就開始了打印日志找 bug 的過程。

排查問題

因為并發(fā)時使用到了 sync 等待全部協(xié)程結(jié)束,起初以為是 sync 異步等待出了問題;

打印日志發(fā)現(xiàn),正常執(zhí)行了 500 次下載,執(zhí)行完成下載之后,繼續(xù)執(zhí)行的轉(zhuǎn)碼操作,排除 sync 異步等待有問題;

代碼如下:

import (
   "github.com/satori/go.uuid"
   "sync"
)
func downloadFiles(nWait *sync.WaitGroup, urls []interface{}, successFiles *[]string, failedFiles *[]string) {
   // 遍歷 urls 進行下載
   for _, value := range urls {
   go func(value interface{}) {
   defer nWait.Done()                                                     // 執(zhí)行結(jié)束,協(xié)程減 1
   fullname := config.TranscodeDownloadPath + "/" + uuid.NewV4().String() // 需要確保文件名的唯一性 (防止不同用戶同一時間操作了同一文件,導致轉(zhuǎn)碼失敗)
   err := utils.DownloadCeph(value.(string), fullname)                    // 下載文件
   // 下載文件狀態(tài)記錄
   if err != nil {
   *failedFiles = append(*failedFiles, fullname)
   } else {
   *successFiles = append(*successFiles, fullname)
   }
   }(value)
   }
}
// 前端傳入的圖片 url
strUrlList := req["strUrlList"]
// 初始化變量
nWait := sync.WaitGroup{}          // 多協(xié)程異步等待
var successFiles []string  // 下載成功文件
var failedFiles []string           // 下載失敗文件
// 遍歷 strUrlList 進行下載
log.Error("開始下載!長度:", len(strUrlList))
nWait.Add(len(strUrlList)) // 等待協(xié)程數(shù)
downloadFiles(&nWait, strUrlList, &successFiles, &failedFiles)
nWait.Wait() // 阻塞,等待完成
log.Error("下載結(jié)束!長度:", len(successFiles))
//...
log.Error("下載轉(zhuǎn)碼!")
//...

日志如下:

2022-10-29 21:28:51.996 ERROR   services/tools.go:149   開始下載!長度:500
2022-10-29 21:28:52.486 ERROR   services/tools.go:153   下載結(jié)束!長度:499
2022-10-29 21:28:52.486 ERROR   services/tools.go:155   開始轉(zhuǎn)碼!

打印更詳細的日志,對 for range 循環(huán)內(nèi)的邏輯進行排查;

在單個 for 循環(huán)結(jié)束時增加日志:

log.Error("下載協(xié)程結(jié)束: ", len(*successFiles))

發(fā)現(xiàn)一處特殊的日志:

2022-10-29 21:40:38.407 ERROR   services/tools.go:35    下載協(xié)程結(jié)束: 63
2022-10-29 21:40:38.407 ERROR   services/tools.go:35    下載協(xié)程結(jié)束: 64
2022-10-29 21:40:38.407 ERROR   services/tools.go:35    下載協(xié)程結(jié)束: 65
2022-10-29 21:40:38.407 ERROR   services/tools.go:35    下載協(xié)程結(jié)束: 65
2022-10-29 21:40:38.408 ERROR   services/tools.go:35    下載協(xié)程結(jié)束: 66
2022-10-29 21:40:38.408 ERROR   services/tools.go:35    下載協(xié)程結(jié)束: 67

兩次長度都是 65,切片長度沒有發(fā)生變化,同一時間點執(zhí)行兩次切片 append 方法,會偶現(xiàn)一次失效,問題原因找到;

解決問題

使用切片索引進行賦值,不再使用 append ;

修復代碼如下:

import (
   "github.com/satori/go.uuid"
   "sync"
)
func downloadFiles(nWait *sync.WaitGroup, urls []interface{}, successFiles *[]string, failedFiles *[]string) {
   // 遍歷 urls 進行下載
   for index, value := range urls {
   go func(index int, value interface{}) {
   defer nWait.Done()                                                     // 執(zhí)行結(jié)束,協(xié)程減 1
   fullname := config.TranscodeDownloadPath + "/" + uuid.NewV4().String() // 需要確保文件名的唯一性 (防止不同用戶同一時間操作了同一文件,導致轉(zhuǎn)碼失敗)
   err := utils.DownloadCeph(value.(string), fullname)                    // 下載文件
   // 下載文件狀態(tài)記錄
   if err != nil {
   (*failedFiles)[index] = fullname
   } else {
   (*successFiles)[index] = fullname
   }
   }(index, value)
   }
}
// 前端傳入的圖片 url
strUrlList := req["strUrlList"]
// 初始化變量
nWait := sync.WaitGroup{}                                        // 多協(xié)程異步等待
successFiles := make([]string, len(strUrlList), len(strUrlList)) // 下載成功文件
failedFiles := make([]string, len(strUrlList), len(strUrlList))  // 下載失敗文件
// 遍歷 strUrlList 進行下載
nWait.Add(len(strUrlList)) // 等待協(xié)程數(shù)
downloadFiles(&nWait, strUrlList, &successFiles, &failedFiles)
nWait.Wait() // 阻塞,等待完成

以上就是“go高并發(fā)時append出錯怎么解決”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

分享文章:go高并發(fā)時append出錯怎么解決
URL地址:http://www.chinadenli.net/article0/iiiiio.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供標簽優(yōu)化微信小程序網(wǎng)站維護用戶體驗面包屑導航網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設公司