欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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è)過程中發(fā)現(xiàn),會(huì)偶現(xiàn)下載后只轉(zhuǎn)換了 499 個(gè)圖片或更少的情況(全部下載、轉(zhuǎn)碼成功的條件下);

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

排查問題

因?yàn)椴l(fā)時(shí)使用到了 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 進(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("開始下載!長(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   開始下載!長(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   開始轉(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)度沒有發(fā)生變化,同一時(shí)間點(diǎn)執(zhí)行兩次切片 append 方法,會(huì)偶現(xià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語言基礎(chǔ)反射示例詳解

    Go語言基礎(chǔ)反射示例詳解

    這篇文章主要為大家介紹了Go語言基礎(chǔ)關(guān)于反射示例的內(nèi)容詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2021-11-11
  • Golang中crypto/rand庫的使用技巧與最佳實(shí)踐

    Golang中crypto/rand庫的使用技巧與最佳實(shí)踐

    在Golang的眾多隨機(jī)數(shù)生成庫中,crypto/rand?是一個(gè)專為加密安全設(shè)計(jì)的庫,本文主要介紹了Golang中crypto/rand庫的使用技巧與最佳實(shí)踐,感興趣的可以了解一下
    2024-02-02
  • Golang匯編之控制流深入分析講解

    Golang匯編之控制流深入分析講解

    這篇文章主要介紹了Golang匯編之控制流,程序執(zhí)行的流程主要有順序、分支和循環(huán)幾種執(zhí)行流程,本節(jié)主要討論如何將Go語言的控制流比較直觀地轉(zhuǎn)譯為匯編程序,或者說如何以匯編思維來編寫Go語言代碼,感興趣的同學(xué)可以參考下文
    2023-05-05
  • 一文帶你了解Go語言中的匿名函數(shù)

    一文帶你了解Go語言中的匿名函數(shù)

    無論是在Go語言還是其他編程語言中,匿名函數(shù)都扮演著重要的角色,本文將詳細(xì)介紹Go語言中匿名函數(shù)的概念和使用方法,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-06-06
  • Beego AutoRouter工作原理解析

    Beego AutoRouter工作原理解析

    這篇文章主要為大家介紹了Beego AutoRouter工作原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Golang微服務(wù)框架Kratos實(shí)現(xiàn)Kafka消息隊(duì)列的方法

    Golang微服務(wù)框架Kratos實(shí)現(xiàn)Kafka消息隊(duì)列的方法

    消息隊(duì)列是大型分布式系統(tǒng)不可缺少的中間件,也是高并發(fā)系統(tǒng)的基石中間件,所以掌握好消息隊(duì)列MQ就變得極其重要,在本文當(dāng)中,您將了解到:什么是消息隊(duì)列?什么是Kafka?怎樣在微服務(wù)框架Kratos當(dāng)中應(yīng)用Kafka進(jìn)行業(yè)務(wù)開發(fā),需要的朋友可以參考下
    2023-09-09
  • Golang中fsnotify包監(jiān)聽文件變化的原理詳解

    Golang中fsnotify包監(jiān)聽文件變化的原理詳解

    Golang提供了一個(gè)強(qiáng)大的fsnotify包,它能夠幫助我們輕松實(shí)現(xiàn)文件系統(tǒng)的監(jiān)控,本文將深入探討fsnotify包的原理,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-12-12
  • Go 第三方庫之類型轉(zhuǎn)換問題

    Go 第三方庫之類型轉(zhuǎn)換問題

    今天給大家介紹一個(gè)第三方庫,專門處理類型轉(zhuǎn)換的問題。對(duì)Go 第三方庫之類型轉(zhuǎn)換問題感興趣的朋友跟隨小編一起看看吧
    2021-08-08
  • Go語言學(xué)習(xí)之golang-jwt/jwt的教程分享

    Go語言學(xué)習(xí)之golang-jwt/jwt的教程分享

    jwt是?json?web?token的簡(jiǎn)稱。go使用jwt目前,主流使用的jwt庫是golang-jwt/jwt。本文就來和大家講講golang-jwt/jwt的具體使用,需要的可以參考一下
    2023-01-01
  • 利用go-kit組件進(jìn)行服務(wù)注冊(cè)與發(fā)現(xiàn)和健康檢查的操作

    利用go-kit組件進(jìn)行服務(wù)注冊(cè)與發(fā)現(xiàn)和健康檢查的操作

    這篇文章主要介紹了利用go-kit組件進(jìn)行服務(wù)注冊(cè)與發(fā)現(xiàn)和健康檢查的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04

最新評(píng)論