


Was ist die beste Vorgehensweise in Golang, um den Abschlussstatus von zwei Goroutinen innerhalb einer dritten Goroutine zu verfolgen?
Was ist die beste Vorgehensweise in Golang, um den Abschlussstatus von zwei Goroutinen in einer dritten Goroutine zu verfolgen? Um in Golang den Abschlussstatus von zwei Goroutinen zu verfolgen und ihre Ergebnisse in einer dritten Goroutine zu verarbeiten, besteht die beste Vorgehensweise darin, WaitGroup aus dem Synchronisierungspaket zu verwenden. WaitGroup ermöglicht es uns, in der Haupt-Goroutine auf die Fertigstellung anderer Goroutinen zu warten. Zuerst müssen wir ein WaitGroup-Objekt erstellen und die Add-Methode in der Haupt-Goroutine aufrufen, um die Anzahl der wartenden Goroutinen festzulegen. Anschließend wird am Ende jeder Goroutine die Done-Methode aufgerufen, um den Abschluss dieser Goroutine zu signalisieren. Schließlich wird in der dritten Goroutine die Wait-Methode aufgerufen, um auf den Abschluss aller Goroutinen zu warten. Auf diese Weise können wir die Ergebnisse beider Goroutinen sicher verfolgen und verarbeiten. Dies ist die beste Vorgehensweise in Golang, um den Abschlussstatus mehrerer Goroutinen zu verfolgen.
Frageninhalt
Ich habe drei Goroutinen gleichzeitig laufen lassen. Zwei von ihnen führen eine Verarbeitung durch und senden ihre Ergebnisse an den Ergebniskanal. Die dritte Goroutine „zählt“ die Ergebnisse, indem sie die Ergebniskanäle liest. Ich könnte eine Wartegruppe verwenden, um auf den Abschluss der beiden Berechnungs-Goroutinen zu warten und dann über die Ergebniskanäle zu iterieren, um die Ergebnisse zu zählen, aber das lässt sich nicht skalieren und erfordert, dass ich einen gepufferten Ergebniskanal mit einer riesigen Puffergröße erstelle, was inakzeptabel ist im Produktionscode.
Ich möchte die Ergebnisse zählen, während die Verarbeitung läuft, aber ich möchte das Programm nicht beenden, bevor die Zählung abgeschlossen ist. Was sind die Best Practices, um dies in Go zu erreichen?
Das ist meine aktuelle Methode und sie funktioniert großartig. Ich frage mich, ob es einen besseren Weg gibt, da das etwas umständlich erscheint?
package main import ( "fmt" "sync" ) type T struct{} func main() { var widgetInventory int = 1000 transactions := make(chan int, 100) salesDone := make(chan T) purchasesDone := make(chan T) var wg sync.WaitGroup fmt.Println("Starting inventory count = ", widgetInventory) go makeSales(transactions, salesDone) go newPurchases(transactions, purchasesDone) wg.Add(1) go func() { salesAreDone := false purchasesAreDone := false for { select { case transaction := <-transactions: widgetInventory += transaction case <-salesDone: salesAreDone = true case <-purchasesDone: purchasesAreDone = true default: if salesAreDone && purchasesAreDone { wg.Done() return } } } }() wg.Wait() fmt.Println("Ending inventory count = ", widgetInventory) } func makeSales(transactions chan int, salesDone chan T) { for i := 0; i < 3000; i++ { transactions <- -100 } salesDone <- struct{}{} } func newPurchases(transactions chan int, purchasesDone chan T) { for i := 0; i < 3000; i++ { transactions <- 100 } purchasesDone <- struct{}{} }
Die Lösung
passt keiner vernünftigen Definitiongut. Sie haben hier eine beliebte for
-Schleife:
for { select { case transaction := <-transactions: widgetInventory += transaction case <-salesDone: salesAreDone = true case <-purchasesDone: purchasesAreDone = true default: if salesAreDone && purchasesAreDone { wg.Done() return } } }
Der default
-Fall wird ausgeführt, solange kein Kanal zum Lesen vorhanden ist. Dies geschieht aufgrund der Art und Weise, wie Kanäle funktionieren, häufig.
Diese leicht angepasste Version des Codes veranschaulicht die „Hitze“ dieser Schleife. Die genauen Ergebnisse variieren und können recht hoch ausfallen.
Default case ran 27305 times
Sie möchten den select
ing 来自通道时,您不希望出现 default
-Fall nicht haben, wenn Sie aus einem Kanal auswählen
, es sei denn, diese Standardeinstellung blockiert auch etwas darin. Sonst kommt es zu solchen Temperaturwechseln.
Besser: Verwenden Sie nil
fähige Kanäle zur Auswahl
Normalerweise möchten Sie in einer Auswahl einen geschlossenen Kanal identifizieren und die Kanalvariable auf nil
; select
永远不会成功地从 nil
select
wird nie erfolgreich aus dem -Kanal lesen, sodass die Auswahl effektiv „deaktiviert“ wird. Betrachten Sie diese modifizierte Version
desCodes: salesDone
和 purchasesDone
都被“发出信号”,我们 close(transactions)
。一旦我们耗尽 transactions
并且它被关闭,我们将 transactions
设置为 nil。我们在 transactions
不为 nil 时循环,在这段代码中,意味着所有通道都是 nil
go func(transactions chan int, salesDone <-chan T, purchasesDone <-chan T) { defer wg.Done() for transactions != nil { select { case transaction, ok := <-transactions: if ok { widgetInventory += transaction } else { transactions = nil } case <-salesDone: salesDone = nil if purchasesDone == nil { close(transactions) } case <-purchasesDone: purchasesDone = nil if salesDone == nil { close(transactions) } } } }(transactions, salesDone, purchasesDone)
salesDone
als auch purchasesDone
„signalisiert“ wurden, schließen wir (Transaktionen)
. Sobald wir transactions
erschöpft haben und main
共享范围。否则,将 transactions
设置为 nil
将写入一个在 goroutine 之间共享的变量。然而在这种情况下,无论如何,这并不重要,因为我们“知道”我们是最后一个从 transactions
es geschlossen ist, setzen wir transactions
auf Null. Wir durchlaufen eine Schleife, wenn transactions
nicht Null ist, was in diesem Code bedeutet, dass alle Kanäle
Subtiler, aber wichtiger Punkt: Ich übergebe einen Kanal an diese Funktion, damit ihre Referenz den Gültigkeitsbereich nicht mit
main
teilt. Andernfalls wird durch Setzen von transactions
auf in eine Variable geschrieben, die von Goroutinen gemeinsam genutzt wird. In diesem Fall spielt es jedoch sowieso keine Rolle, da wir „wissen“, dass wir die letzten sind, die aus transactions
lesen. transactions
的生产。然后你想排空 transactions
。一旦通道关闭并排空,main
select
来执行此操作。而 select
Wenn Sie darüber nachdenken, was Sie hier tun, müssen Sie warten, bis beide Produzenten die Paarung abgeschlossen haben
Sie müssen nicht 🎜 für jeden „Arbeiter“ einen Fall haben, was wohl ziemlich unelegant ist; Sie müssen mehrere Arbeiter fest codieren und den „Abschluss“-Kanal einzeln behandeln. 🎜 🎜Was Sie tun müssen, ist:🎜
- 除了为生产者使用一个
var resultswgsync.WaitGroup
之外,还为消费者添加一个。 - 生产者
defer wg.Done()
- 消费者
defer resultswg.Done()
在遍历transactions
之前:go func() { defer resultswg.Done() for transaction := range transactions { widgetInventory += transaction } }()
Nach dem Login kopieren - main 处理等待生产者、关闭事务以结束范围,然后等待消费者:
wg.Wait() close(transactions) resultswg.Wait()
Nach dem Login kopieren
package main import ( "fmt" "sync" ) func main() { var widgetInventory int = 1000 transactions := make(chan int, 100) var wg, resultswg sync.WaitGroup fmt.Println("Starting inventory count = ", widgetInventory) wg.Add(2) go makeSales(transactions, &wg) go newPurchases(transactions, &wg) resultswg.Add(1) go func() { defer resultswg.Done() for transaction := range transactions { widgetInventory += transaction } }() wg.Wait() close(transactions) resultswg.Wait() fmt.Println("Ending inventory count = ", widgetInventory) } func makeSales(transactions chan int, wg *sync.WaitGroup) { defer wg.Done() for i := 0; i < 3000; i++ { transactions <- -100 } } func newPurchases(transactions chan int, wg *sync.WaitGroup) { defer wg.Done() for i := 0; i < 3000; i++ { transactions <- 100 } }
您可以在这里看到,在此模式中可以有任意数量的生产者;您只需为每个生产者添加 wg.Add(1)
即可。
当我不知道每个工作人员会返回多少结果时,我一直使用这种模式来并行化工作。我发现它很容易理解,并且比尝试 select
多个通道简单得多。事实上,我什至想说,如果您发现自己从多个渠道进行 select
ing,您应该退后一步,确保它对您来说确实有意义。我使用 select
的频率远远低于使用等待组的频率。
Das obige ist der detaillierte Inhalt vonWas ist die beste Vorgehensweise in Golang, um den Abschlussstatus von zwei Goroutinen innerhalb einer dritten Goroutine zu verfolgen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen



Seit seiner Einführung im Jahr 2009 hat sich Bitcoin zu einem führenden Unternehmen in der Welt der Kryptowährungen entwickelt und sein Preis hat enorme Schwankungen erfahren. Um einen umfassenden historischen Überblick zu bieten, stellt dieser Artikel Bitcoin-Preisdaten von 2009 bis 2025 zusammen und deckt wichtige Marktereignisse, Änderungen der Marktstimmung und wichtige Faktoren ab, die die Preisbewegungen beeinflussen.

Bitcoin hat als Kryptowährung seit seiner Einführung erhebliche Marktvolatilität erlebt. Dieser Artikel bietet einen Überblick über den historischen Preis von Bitcoin seit seiner Geburt, um den Lesern zu helfen, seine Preistrends und Schlüsselmomente zu verstehen. Durch die Analyse der historischen Preisdaten von Bitcoin können wir die Einschätzung des Marktes über seinen Wert und die Faktoren, die seine Schwankungen beeinflussen, verstehen und eine Grundlage für zukünftige Investitionsentscheidungen schaffen.

Seit seiner Gründung im Jahr 2009 hat der Preis von Bitcoin im November 2021 auf 69.044,77 USD auf 69.044,77 USD gestiegen und im Dezember 2018 auf 3.191,22 USD gesunken. Ab Dezember 2024 hat der jüngste Preis 100.204 USD überschritten.

Echtzeit-Bitcoin-USD-Preis Faktoren, die den Bitcoin -Preis beeinflussen Indikatoren für die Vorhersage zukünftiger Bitcoin -Preise Hier finden Sie einige wichtige Informationen zum Preis von Bitcoin in den Jahren 2018-2024:

Die Methode zur Anpassung der Größe der Größe der Größe der Größe in CSS ist mit Hintergrundfarben einheitlich. In der täglichen Entwicklung begegnen wir häufig Situationen, in denen wir die Details der Benutzeroberfläche wie Anpassung anpassen müssen ...

Wie kann man den 45-Grad-Kurveneffekt des Segmenters erreichen? Bei der Implementierung des Segmenters verwandeln Sie den rechten Rand in eine 45-Grad-Kurve, wenn Sie auf die linke Schaltfläche klicken, und der Punkt ...

Ja, die H5-Seitenproduktion ist eine wichtige Implementierungsmethode für die Front-End-Entwicklung, die Kerntechnologien wie HTML, CSS und JavaScript umfasst. Entwickler bauen dynamische und leistungsstarke H5 -Seiten auf, indem sie diese Technologien geschickt kombinieren, z. B. die Verwendung der & lt; canvas & gt; Tag, um Grafiken zu zeichnen oder JavaScript zu verwenden, um das Interaktionsverhalten zu steuern.

Das Problem der Containeröffnung aufgrund einer übermäßigen Auslassung von Text unter Flex -Layout und Lösungen werden verwendet ...
