最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

go高并發(fā)時(shí)append方法偶現(xiàn)錯(cuò)誤解決分析

 更新時(shí)間:2022年10月31日 12:01:08   作者:gokingliu  
這篇文章主要為大家介紹了go高并發(fā)時(shí)append方法偶現(xiàn)錯(cuò)誤解決分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

背景

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

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

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

然后就開(kāi)始了打印日志找 bug 的過(guò)程。

排查問(wèn)題

因?yàn)椴l(fā)時(shí)使用到了 sync 等待全部協(xié)程結(jié)束,起初以為是 sync 異步等待出了問(wèn)題;

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

代碼如下:

import (
	"github.com/satori/go.uuid"
	"sync"
)
func downloadFiles(nWait *sync.WaitGroup, urls []interface{}, successFiles *[]string, failedFiles *[]string) {
	// 遍歷 urls 進(jìn)行下載
	for _, value := range urls {
		go func(value interface{}) {
			defer nWait.Done()                                                     // 執(zhí)行結(jié)束,協(xié)程減 1
			fullname := config.TranscodeDownloadPath + "/" + uuid.NewV4().String() // 需要確保文件名的唯一性 (防止不同用戶同一時(shí)間操作了同一文件,導(dǎo)致轉(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 進(jìn)行下載
log.Error("開(kāi)始下載!長(zhǎng)度:", len(strUrlList))
nWait.Add(len(strUrlList)) // 等待協(xié)程數(shù)
downloadFiles(&nWait, strUrlList, &successFiles, &failedFiles)
nWait.Wait() // 阻塞,等待完成
log.Error("下載結(jié)束!長(zhǎng)度:", len(successFiles))
//...
log.Error("下載轉(zhuǎn)碼!")
//...

日志如下:

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

打印更詳細(xì)的日志,對(duì) for range 循環(huán)內(nèi)的邏輯進(jìn)行排查;
在單個(gè) for 循環(huán)結(jié)束時(shí)增加日志:

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

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

解決問(wèn)題

使用切片索引進(jìn)行賦值,不再使用 append ;

修復(fù)代碼如下:

import (
	"github.com/satori/go.uuid"
	"sync"
)
func downloadFiles(nWait *sync.WaitGroup, urls []interface{}, successFiles *[]string, failedFiles *[]string) {
	// 遍歷 urls 進(jìn)行下載
	for index, value := range urls {
		go func(index int, value interface{}) {
			defer nWait.Done()                                                     // 執(zhí)行結(jié)束,協(xié)程減 1
			fullname := config.TranscodeDownloadPath + "/" + uuid.NewV4().String() // 需要確保文件名的唯一性 (防止不同用戶同一時(shí)間操作了同一文件,導(dǎo)致轉(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 進(jìn)行下載
nWait.Add(len(strUrlList)) // 等待協(xié)程數(shù)
downloadFiles(&nWait, strUrlList, &successFiles, &failedFiles)
nWait.Wait() // 阻塞,等待完成

以上就是go高并發(fā)時(shí)append方法偶現(xiàn)錯(cuò)誤解決分析的詳細(xì)內(nèi)容,更多關(guān)于go高并發(fā)append錯(cuò)誤的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 一文帶你搞懂Go如何讀寫(xiě)Excel文件

    一文帶你搞懂Go如何讀寫(xiě)Excel文件

    Excelize是一個(gè)用純Go語(yǔ)言編寫(xiě)的庫(kù),提供了一組函數(shù),可以對(duì)XLAM?/?XLSM?/?XLSX?/?XLTM?/?XLTX文件進(jìn)行讀寫(xiě)。支持讀寫(xiě)由Microsoft?Excel?2007及以后版本生成的電子表格文檔。本文就將用它實(shí)現(xiàn)讀寫(xiě)Excel文件操作,感興趣的可以學(xué)習(xí)一下
    2022-11-11
  • 詳解Golang中文件系統(tǒng)事件監(jiān)聽(tīng)

    詳解Golang中文件系統(tǒng)事件監(jiān)聽(tīng)

    文件系統(tǒng)事件是指文件系統(tǒng)相關(guān)的各種操作和狀態(tài)變化,當(dāng)一個(gè)應(yīng)用層的進(jìn)程操作文件或目錄時(shí),會(huì)觸發(fā)system call,內(nèi)核的notification子系統(tǒng)可以守在那里,把該進(jìn)程對(duì)文件的操作上報(bào)給應(yīng)用層的監(jiān)聽(tīng)進(jìn)程,這篇文章主要介紹了Golang之文件系統(tǒng)事件監(jiān)聽(tīng),需要的朋友可以參考下
    2024-01-01
  • golang中的net/http庫(kù)基本使用詳解

    golang中的net/http庫(kù)基本使用詳解

    今天給大家分享golang中的net/http庫(kù)基本使用方法,文章開(kāi)頭給大家詳細(xì)介紹了標(biāo)準(zhǔn)庫(kù)net/http如何處理一個(gè)請(qǐng)求,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-04-04
  • Goland的設(shè)置與配置全過(guò)程

    Goland的設(shè)置與配置全過(guò)程

    這篇文章主要介紹了Goland的設(shè)置與配置全過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • Go應(yīng)該如何實(shí)現(xiàn)二級(jí)緩存

    Go應(yīng)該如何實(shí)現(xiàn)二級(jí)緩存

    本文主要介紹了Go二級(jí)緩存,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • golang官方嵌入文件到可執(zhí)行程序的示例詳解

    golang官方嵌入文件到可執(zhí)行程序的示例詳解

    這篇文章主要介紹了golang官方嵌入文件到可執(zhí)行程序,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02
  • Go標(biāo)準(zhǔn)庫(kù)strconv實(shí)現(xiàn)string類(lèi)型與其他基本數(shù)據(jù)類(lèi)型之間轉(zhuǎn)換

    Go標(biāo)準(zhǔn)庫(kù)strconv實(shí)現(xiàn)string類(lèi)型與其他基本數(shù)據(jù)類(lèi)型之間轉(zhuǎn)換

    這篇文章主要為大家介紹了Go標(biāo)準(zhǔn)庫(kù)strconv實(shí)現(xiàn)string類(lèi)型與其他基本數(shù)據(jù)類(lèi)型之間轉(zhuǎn)換示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • 淺談GoLang幾種讀文件方式的比較

    淺談GoLang幾種讀文件方式的比較

    這篇文章主要介紹了淺談GoLang幾種讀文件方式的比較,一般來(lái)說(shuō)常用的有三種。使用Read加上buffer,使用bufio庫(kù)和ioutil 庫(kù),非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2019-01-01
  • Go語(yǔ)言七篇入門(mén)教程一簡(jiǎn)介初識(shí)

    Go語(yǔ)言七篇入門(mén)教程一簡(jiǎn)介初識(shí)

    本篇是Go語(yǔ)言七篇入門(mén)系列第一篇Go語(yǔ)言初識(shí)及簡(jiǎn)單介紹,從現(xiàn)在開(kāi)始一起打開(kāi)Go語(yǔ)言的學(xué)習(xí)大門(mén)吧,希望能夠有所幫助,祝大家多多進(jìn)步
    2021-11-11
  • golang數(shù)組-----尋找數(shù)組中缺失的整數(shù)方法

    golang數(shù)組-----尋找數(shù)組中缺失的整數(shù)方法

    這篇文章主要介紹了golang數(shù)組-----尋找數(shù)組中缺失的整數(shù)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12

最新評(píng)論

石林| 土默特右旗| 兖州市| 镇安县| 黑山县| 昌黎县| 房山区| 泸溪县| 墨竹工卡县| 板桥市| 龙南县| 万盛区| 万荣县| 邹城市| 桑植县| 罗平县| 锡林郭勒盟| 萨迦县| 铅山县| 安多县| 尼玛县| 霍邱县| 沁水县| 永德县| 博爱县| 海伦市| 东乡县| 内丘县| 扎囊县| 张家港市| 天镇县| 高平市| 泽库县| 夏河县| 通江县| 集贤县| 杭州市| 临沂市| 榆中县| 静海县| 光山县|