Heim  >  Artikel  >  Backend-Entwicklung  >  ## Warum ist das Kopieren von Instanzen von Go-Typen mit Zeigerempfängermethoden gefährlich?

## Warum ist das Kopieren von Instanzen von Go-Typen mit Zeigerempfängermethoden gefährlich?

Linda Hamilton
Linda HamiltonOriginal
2024-10-25 10:54:30185Durchsuche

## Why is Copying Instances of Go Types with Pointer Receiver Methods Dangerous?

Fallstricke beim Kopieren von Instanzen mit Zeigerempfängermethoden

In Go, wenn alle Methoden für einen benannten Typ T einen Empfängertyp von T selbst haben (nicht *T), das Kopieren von Instanzen dieses Typs gilt als sicher. Dies liegt daran, dass jeder Methodenaufruf zwangsläufig eine Kopie bearbeitet und so sicherstellt, dass der ursprüngliche Wert unverändert bleibt. Wenn jedoch eine Methode für T einen Zeigerempfänger hat, kann das Kopieren von Instanzen von T gefährlich sein.

Erklärung

Beim Aufrufen einer Methode wird der Wert der Methode aufgerufen on wird zuerst kopiert und die Kopie wird als Empfänger übergeben. Wenn ein Typ nur über Methoden mit Wertempfängern verfügt, ist gewährleistet, dass die Methoden unabhängig von ihren Aktionen den ursprünglichen Wert nicht ändern können. Dies liegt daran, dass immer eine Kopie verwendet wird, die das Original vor unbeabsichtigten Änderungen schützt.

Wenn ein Typ jedoch Methoden mit Zeigerempfängern hat, können diese Methoden den ursprünglichen Zeigerwert und nicht seine Kopie ändern. Dies liegt daran, dass die Methode einen Zeiger auf den ursprünglichen Wert erhält, wodurch sie die zugrunde liegenden Daten ändern kann.

Beispiel

Betrachten Sie einen Wrapper-Typ Wrapper:

type Wrapper struct {
    v int
    p *int
}

Mit einer Set()-Methode, um sicherzustellen, dass beide Felder den gleichen Wert enthalten:

func (w *Wrapper) Set(v int) {
    w.v = v
    *w.p = v
}

Wenn wir eine Instanz von Wrapper erstellen:

a := Wrapper{v: 0, p: new(int)}

Und anschließend eine erstellen Kopie (b) von a:

b := a

Nachdem a mit Set() auf 1 gesetzt wurde:

a.Set(1)

Wir würden erwarten, dass sowohl a als auch b ihre Felder auf 1 gesetzt haben. Das Drucken ihrer Werte zeigt jedoch eine andere Geschichte:

fmt.Printf("a.v=%d, a.p=%d;  b.v=%d, b.p=%d\n", a.v, *a.p, b.v, *b.p)

Ausgabe:

a.v=1, a.p=1;  b.v=0, b.p=1

Der Grund für diese Diskrepanz ist, dass der Zeiger in b zwar kopiert wird, aber immer noch auf denselben verweist zugrunde liegende Daten als Zeiger in a. Wenn Set() den angegebenen Wert ändert, wirkt sich dies auf beide Kopien von Wrapper aus. Allerdings bleibt das Nicht-Zeigerfeld v zwischen a und b unterschiedlich.

Best Practice

Um dieses Problem zu vermeiden, wird empfohlen, keine Instanzen von Typen mit zu kopieren Zeigerempfängermethoden. Wenn das Arbeiten mit Zeigerwerten erforderlich ist, ist das Kopieren des Zeigers selbst (*T) eine praktikable Alternative.

Das obige ist der detaillierte Inhalt von## Warum ist das Kopieren von Instanzen von Go-Typen mit Zeigerempfängermethoden gefährlich?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn