Golang: anonyme Struktur und leere Struktur
http://play.golang.org/p/vhaKi5uVmm
package main
import "fmt"
var battle = make(chan string)
func warrior(name string, done chan struct{}) {
select {
case opponent := <-battle:
fmt.Printf("%s beat %s\n", name, opponent)
case battle <- name:
//I lost :-(
}
done <- struct{}{}
}
func main() {
done := make(chan struct{})
langs := []string{"Go", "C", "C++", "Java", "Perl", "Python"}
for _, l := range langs { go warrior(l, done) }
for _ = range langs { <-done }
}
[1. Frage]
done <- struct{}{}
Wie und Warum brauchen wir diese seltsam aussehenden struct? Ist es leer, struct oder anonyme struct? Ich habe es gegoogelt, konnte aber nicht die richtige Antwort oder die Dokumentation zu erklären.
Die original-Quelle ist von Andrew Gerrand sprechen
http://nf.wh3rd.net/10things/#10
Hier
make(chan struct{})
fertig ist ein channel vom Typ struct{}
Also versuchte ich mit
done <- struct{}
Aber es funktioniert nicht. Warum brauche ich eine extra Klammern für diese Zeile?
done <- struct{}{}
[2. Frage]
for _ = range langs { <-done }
Warum benötige ich diese Zeile? Ich weiß, dass diese Zeile ist notwendig, weil ohne diese Zeile keine Ausgabe. Aber Warum und was bewirkt diese Zeile? Und was es notwendig macht, in diesem code? Ich weiß, dass <-done
erhalten Werte aus dem Kanal getan und löschen der empfangenen Werte. Aber warum muss ich das tun?
Dank!
InformationsquelleAutor der Frage | 2013-12-27
Du musst angemeldet sein, um einen Kommentar abzugeben.
struct{}{}
ist ein zusammengesetztes literal vom Typstruct{}
der Typ des Wertes, gefolgt von einer Klammer-gebundene Liste von composite-Elementen.for _ = range langs { <-done }
ist zu warten, bis alle die goroutines für allelangs
geschickt habendone
Nachrichten.InformationsquelleAutor der Antwort peterSO
Beachten Sie, dass ein interessanter Aspekt der Verwendung von struct{} für die Art geschoben, um einen Kanal (im Gegensatz zu int oder bool), ist, dass die Größe eine leere struct... 0!
Siehe den jüngsten Artikel "Die leere struct" (März 2014) von Dave Cheney.
Können Sie so viele
struct{}
wie Sie wollen (struct{}{}
) drücken Sie auf Ihrem Kanal: deine Speicher sind nicht betroffen.Aber Sie können es verwenden, für die Signalisierung zwischen go-Routinen, wie dargestellt, in "Neugierig Kanäle".
Und behalten Sie alle anderen Vorteile in Verbindung, um einen struct:
Siehe zum Beispiel die Globale var
errServerKeyExchange
in der Datei, wo die leere structrsaKeyAgreement
definiert ist.InformationsquelleAutor der Antwort VonC
struct{}
ist eine Art (insbesondere, eine Struktur, die keine Mitglieder hat). Wenn Sie einenFoo
können Sie erstellen, die einen Wert dieses Typs in einem Ausdruck mitFoo{field values, ...}
. Putting dies zusammenstruct{}{}
ist ein Wert vom Typstruct{}
- das, was der Kanal erwartet.Den
main
Funktion laichtwarrior
goroutines, die schreiben an diedone
Kanal, wenn Sie fertig sind. Die letztenfor
block liest aus diesem Kanal, sicherzustellen, dassmain
nicht zurück, bis alle die goroutines abgeschlossen haben. Das ist wichtig, denn das Programm wird beendet, wenn Siemain
abgeschlossen ist, unabhängig davon, ob es gibt andere goroutines läuft.InformationsquelleAutor der Antwort James Henstridge
Gute Fragen,
Den ganzen Sinn der struct-Kanal in diesem Szenario ist es einfach, um den Abschluss signalisiert, dass etwas sinnvolles passiert. Kanal-Typ ist eigentlich egal, er hätte einen int-oder bool-erreichen den gleichen Effekt. Was wichtig ist, ist, dass sein code ausgeführt wird, die in einer synchronisierten Art und Weise, wie er ' s tun, die notwendige Buchführung zu signal und die Bewegung an wichtigen stellen.
Stimme ich die syntax von
struct{}{}
sieht seltsam auf den ersten, weil in diesem Beispiel ist er der Deklaration einer struct, und erstellen Sie Sie in-line, also die zweite Reihe von Klammern.Wenn Sie einem bereits vorhandenen Objekt wie:
Könnten Sie es so:
b := Book{}
benötigen Sie nur eine Reihe von Klammern, weil das Buch struct hat bereits erklärt worden.InformationsquelleAutor der Antwort Ralph Caraveo
done
- Kanal wird verwendet, um Benachrichtigungen vonwarrior
Methode zeigt, dass die Arbeiter fertig ist die Verarbeitung. Also den Kanal kann alles sein, zum Beispiel:Erklären wir
done := make(chan bool)
als einen Kanal erhält, dass die bool-Wert, und sendentrue
am Endewarrior
statt. Dieser funktioniert! Sie können auch festlegen, wiedone
Kanal auf einen anderen Typ, es wird nicht egal.1. Also, was ist mit dem seltsamen
done <- struct{}{}
?Es ist nur eine andere Art, die weitergegeben werden, zu kanalisieren. Dies ist ein leeres struct, wenn Sie mit den folgenden vertraut sind:
struct{}
macht keinen Unterschied, außer, dass es enthält keine Felder, und diestruct{}{}
ist nur ein Beispiel heraus. Das beste feature ist es nicht, kostet Speicherplatz!2. for-Schleife Verwendung
Erstellen wir 6 goroutines im hintergrund ausführen mit der Zeile:
Verwenden wir die
for _ = range langs { <-done }
weil die wichtigsten goroutine(wo main-Funktion läuft) wartet nicht, bis goroutins zu beenden.Wenn wir nicht gehören der letzten Zeile, die Chancen sind, sehen wir keine Ausgaben(weil main goroutines beendet, bevor jedes Kind goroutines führt
fmt.Printf
code, und wenn die Haupt-goroutine beendet wird, werden alle untergeordneten goroutines wird, beenden Sie es, und haben keine chance zu laufen sowieso).Also warten wir für alle goroutines zu beenden(es läuft zu Ende, und schicken Sie eine Nachricht an die
done
Kanal), dann beendet.done
Kanal hier ist ein verstopfter Kanal, was bedeutet, dass<-done
blockiert, bis eine Nachricht empfangen wird, aus dem Kanal.Wir haben 6 goroutines in den hintergrund, und verwenden Sie eine for-Schleife, warten wir, bis alle goroutines senden Sie eine Nachricht was bedeutet, dass es fertig ausgeführt ist(weil die
done <-struct{}{}
ist am Ende der Funktion).InformationsquelleAutor der Antwort cizixs