Heim  >  Artikel  >  Backend-Entwicklung  >  Detaillierte Erklärung des Anhängefehlerproblems, wenn Go eine hohe Parallelität aufweist!

Detaillierte Erklärung des Anhängefehlerproblems, wenn Go eine hohe Parallelität aufweist!

藏色散人
藏色散人nach vorne
2022-10-31 16:14:413030Durchsuche

Dieser Artikel wurde von der Kolumne golang-Tutorial geschrieben, um Ihnen die gelegentlichen Fehler in der Append-Methode vorzustellen, wenn go eine hohe Parallelität aufweist. Ich hoffe, dass er Freunden, die sie benötigen, im Detail erklärt wird.

Hintergrund

Bei der Umsetzung der Bildtranskodierungsanforderungen müssen nach dem Herunterladen und Konvertieren von Formaten bis zu 500 Bilder unterstützt werden.

Wenn Sie eins nach dem anderen herunterladen und transkodieren, dauert es zu lange und Sie müssen es verwenden Goroutine zur Implementierung von 500 Bildern, gleichzeitige Transkodierung

Beim Selbsttest wurde jedoch festgestellt, dass nach dem Herunterladen nur 499 Bilder oder weniger konvertiert wurden (vorausgesetzt, alle Downloads und Transkodierungen waren erfolgreich);

Dann beginnen Sie mit dem Drucken von Protokollen, um Fehler zu finden.

Fehlerbehebung

Da die Synchronisierung während der Parallelität verwendet wird, um auf das Ende aller Coroutinen zu warten, dachte ich zunächst, es gäbe ein Problem mit dem asynchronen Warten auf die Synchronisierung.

Ich habe das Protokoll ausgedruckt und festgestellt, dass 500 Downloads normal ausgeführt wurden wurde abgeschlossen, die Ausführung wurde fortgesetzt. Der Transkodierungsvorgang beseitigt Probleme mit dem asynchronen Warten auf die Synchronisierung

Am Ende einer einzelnen for-Schleife Protokoll hinzufügen:

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()                                                     // 执行结束,协程减 1
   fullname := config.TranscodeDownloadPath + "/" + uuid.NewV4().String() // 需要确保文件名的唯一性 (防止不同用户同一时间操作了同一文件,导致转码失败)
   err := utils.DownloadCeph(value.(string), fullname)                    // 下载文件
   // 下载文件状态记录
   if err != nil {
   *failedFiles = append(*failedFiles, fullname)
   } else {
   *successFiles = append(*successFiles, fullname)
   }
   }(value)
   }
}
// 前端传入的图片 url
strUrlList := req["strUrlList"]
// 初始化变量
nWait := sync.WaitGroup{}          // 多协程异步等待
var successFiles []string  // 下载成功文件
var failedFiles []string           // 下载失败文件
// 遍历 strUrlList 进行下载
log.Error("开始下载!长度:", len(strUrlList))
nWait.Add(len(strUrlList)) // 等待协程数
downloadFiles(&nWait, strUrlList, &successFiles, &failedFiles)
nWait.Wait() // 阻塞,等待完成
log.Error("下载结束!长度:", len(successFiles))
//...
log.Error("下载转码!")
//...

Ein spezielles Protokoll gefunden:

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   下载结束!长度:499
2022-10-29 21:28:52.486 ERROR   services/tools.go:155   开始转码!

Die Länge beträgt beide Male 65 und die Slice-Länge hat sich nicht geändert, wenn die Slice-Anhängemethode zweimal gleichzeitig ausgeführt wird , ein Fehler wird gefunden.

Lösen Sie das Problem. Verwenden Sie den Slice-Index nicht mehr.

Der Reparaturcode lautet wie folgt:

rrree

Das obige ist der detaillierte Inhalt vonDetaillierte Erklärung des Anhängefehlerproblems, wenn Go eine hohe Parallelität aufweist!. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.im. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen