Ist es in Ordnung, einen Kanal offen zu lassen?


160

Ist es in Ordnung, einen Go-Kanal für immer offen zu lassen (niemals den Kanal schließen), wenn ich nie nach seinem Status überprüfe? Wird es zu Speicherlecks führen? Ist der folgende Code in Ordnung?

func (requestCh chan<- Request) GetResponse(data RequestData) Response {
    reply := make(chan Response)
    requestCh <- Request{data: data, replyCh: reply}
    return <-reply
}

Antworten:


236

Es ist in Ordnung, einen Go-Kanal für immer offen zu lassen und ihn niemals zu schließen. Wenn der Kanal nicht mehr verwendet wird, wird der Müll gesammelt.

Beachten Sie, dass ein Kanal nur geschlossen werden muss, wenn der Empfänger nach einem Schließen sucht. Das Schließen des Kanals ist ein Steuersignal auf dem Kanal, das anzeigt, dass keine weiteren Daten folgen.

Entwurfsfrage: Kanalschluss


3
Ich bin mir nicht sicher, ob ich der Antwort des Links zustimme. Ich hatte einen Speicherverlust im Bereich von 2 GB. Sobald ich das Schließen hinzufügte, wurde der Geysir ein Rinnsal.
Richard

9
@ Richard: Lies den gesamten Thread sorgfältig durch. Der Autor von Go gcund der Autor von gccgosay channel closes sind nicht erforderlich, es sei denn, Sie suchen nach einem close. Das ist ein maßgeblicher Rat.
PeterSO

6
@peterSO, das mag sein, aber ich weiß, was ich gesehen habe und das habe ich gemeldet. Bitte entlassen Sie mich nicht.
Richard

1
Wenn Sie einen gepufferten Kanal haben, sollte das Hinzufügen von Nachrichten Speicher verwenden. Wenn Ihr Kanal jedoch nicht gepuffert ist oder nichts hinzugefügt wird, wächst die Speichernutzung nicht.
Metakeule


31

Ja, es ist in Ordnung, einen Kanal offen zu halten. In dem Programmiersprachenbuch go heißt es:

Sie müssen nicht jeden Kanal schließen, wenn Sie damit fertig sind. Es ist nur erforderlich, einen Kanal zu schließen, wenn es wichtig ist, den empfangenden Goroutinen mitzuteilen, dass alle Daten gesendet wurden. Bei einem Kanal, bei dem der Garbage Collector feststellt, dass er nicht erreichbar ist, werden seine Ressourcen zurückgefordert, unabhängig davon, ob er geschlossen ist oder nicht. (Verwechseln Sie dies nicht mit dem Schließvorgang für geöffnete Dateien. Es ist wichtig, die Close- Methode für jede Datei aufzurufen, wenn Sie damit fertig sind.)


7

Ja, es ist in Ordnung, den Kanal offen zu lassen, und tatsächlich ist es typisch. Ein offener Kanal stellt keinen Verweis auf das Kanalobjekt dar und verhindert daher nicht, dass Müll gesammelt wird.


1

" Ein allgemeines Prinzip bei der Verwendung von Go-Kanälen besteht darin, einen Kanal nicht von der Empfängerseite aus zu schließen und keinen Kanal zu schließen, wenn der Kanal mehrere gleichzeitige Sender hat. "

Wie in der obigen Antwort klar erwähnt, wird jeder Kanal irgendwann GCed, sobald er zur Bereinigung markiert ist. Es ist also in Ordnung, den Kanal nicht geschlossen zu lassen. Der einzige Unterschied besteht darin, dass dieser Kanal möglicherweise gcnach einigen Zyklen verfügbar ist, wenn nicht explizit geschlossen.

Auch die folgenden Artikel dies und das zeigen verschiedene Möglichkeiten, einen Kanal im Fall von 1: N, N: 1 oder M: N zu schließen (Sender: Empfänger)


-5

Go ist Müll gesammelt, so dass Sie nichts wirklich "befreien" müssen.

Es besteht die Möglichkeit, Kanäle zu schließen, aber es wird meistens verwendet, um - der (Kanal) - der Goroutine (oder dem Hauptprogramm) mitzuteilen, dass auf diesem Kanal nichts anderes gesendet wird.


8
AFAIK Selbst in einer Sprache, in der Müll gesammelt wird, ist ein Programmierer immer noch dafür verantwortlich, nicht verwaltete Ressourcen freizugeben, z. B. das Schließen von Dateien, Sockets usw. Muss ich den Kanal wie eine Datei schließen?
Kluyg

3
@Kluyg Die Antwort ist nein. Sie sprechen über Betriebssystemressourcen (welche Kanäle nicht). Dies hängt von einer Ressource und Sprache ab. In der Regel wird jedoch empfohlen, Betriebssystemressourcen manuell zu schließen, nicht weil GC dies nicht tun würde, sondern weil es nicht deterministisch ist. Das häufigste Problem ist, dass zu viele offene Dateien fehlerhaft sind. Sie öffnen weiterhin Dateien ... Sie erwarten, dass GC dies tut ... Ihnen geht nicht der Speicher aus (daher tritt GC nicht ein) ... Ihnen gehen die Dateideskriptoren auf Betriebssystemebene aus. OS beendet den Prozess :)
Pijusn

Ich bin verwirrt darüber, warum dies so viele Abstimmungen gab, während es die ganze Zeit korrekt war und dasselbe wie andere akzeptierte Antworten aussagt ...
eja
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.