Ich bin neu in Go und erlebe eine gewisse kongitive Dissonanz zwischen stapelbasierter Programmierung im C-Stil, bei der automatische Variablen auf dem Stapel und zugewiesenem Speicher auf dem Heap gespeichert sind, und stapelbasierter Programmierung im Python-Stil, bei der die Das einzige, was auf dem Stapel lebt, sind Verweise / Zeiger auf Objekte auf dem Heap.
Soweit ich das beurteilen kann, geben die beiden folgenden Funktionen die gleiche Ausgabe:
func myFunction() (*MyStructType, error) {
var chunk *MyStructType = new(HeaderChunk)
...
return chunk, nil
}
func myFunction() (*MyStructType, error) {
var chunk MyStructType
...
return &chunk, nil
}
dh eine neue Struktur zuweisen und zurückgeben.
Wenn ich das in C geschrieben hätte, hätte der erste ein Objekt auf den Haufen gelegt und der zweite hätte es auf den Stapel gelegt. Der erste würde einen Zeiger auf den Heap zurückgeben, der zweite würde einen Zeiger auf den Stapel zurückgeben, der zum Zeitpunkt der Rückkehr der Funktion verdunstet wäre, was eine schlechte Sache wäre.
Wenn ich es in Python (oder vielen anderen modernen Sprachen außer C #) geschrieben hätte, wäre Beispiel 2 nicht möglich gewesen.
Ich verstehe, dass Go Garbage beide Werte sammelt, also sind beide oben genannten Formen in Ordnung.
Zitieren:
Beachten Sie, dass es im Gegensatz zu C vollkommen in Ordnung ist, die Adresse einer lokalen Variablen zurückzugeben. Der der Variablen zugeordnete Speicher bleibt nach der Rückkehr der Funktion erhalten. Wenn Sie die Adresse eines zusammengesetzten Literals verwenden, wird bei jeder Auswertung eine neue Instanz zugewiesen, sodass wir diese beiden letzten Zeilen kombinieren können.
Aber es wirft ein paar Fragen auf.
1 - In Beispiel 1 wird die Struktur auf dem Heap deklariert. Was ist mit Beispiel 2? Wird das auf dem Stack genauso deklariert wie in C oder geht es auch auf dem Heap?
2 - Wenn Beispiel 2 auf dem Stapel deklariert ist, wie bleibt es verfügbar, nachdem die Funktion zurückgegeben wurde?
3 - Wenn Beispiel 2 tatsächlich auf dem Heap deklariert ist, wie kommt es dann, dass Strukturen eher als Wert als als Referenz übergeben werden? Was ist der Sinn von Zeigern in diesem Fall?
In beiden Fällen würden aktuelle Implementierungen von Go Speicher für einen
struct
TypMyStructType
auf einem Heap zuweisen und dessen Adresse zurückgeben. Die Funktionen sind äquivalent; Die Quelle des Compilers ist dieselbe.Alle Funktions- und Rückgabeparameter werden als Wert übergeben. Der Rückgabeparameterwert mit Typ
*MyStructType
ist eine Adresse.quelle
Laut Go's FAQ :
quelle
Quelle: http://devs.cloudimmunity.com/gotchas-and-common-mistakes-in-go-golang/index.html#stack_heap_vars
quelle
Funktion1 und Funktion2 können Inline-Funktionen sein. Und die Rückgabevariable wird nicht entkommen. Es ist nicht erforderlich, eine Variable auf dem Heap zuzuweisen.
Mein Beispielcode:
Laut Ausgabe von cmd:
Ausgabe:
Wenn der Compiler intelligent genug ist, wird F1 () F2 () F3 () möglicherweise nicht aufgerufen. Weil es keine Mittel gibt.
Es ist egal, ob eine Variable auf einem Heap oder Stack zugewiesen ist, verwenden Sie sie einfach. Schützen Sie es bei Bedarf durch Mutex oder Kanal.
quelle