Heim >Backend-Entwicklung >Golang >Wie geht die „defer'-Anweisung von Go mit der Variablenauswertung um und welche Problemumgehungen gibt es für unerwartetes Verhalten?

Wie geht die „defer'-Anweisung von Go mit der Variablenauswertung um und welche Problemumgehungen gibt es für unerwartetes Verhalten?

Linda Hamilton
Linda HamiltonOriginal
2024-12-18 13:32:15286Durchsuche

How Does Go's `defer` Statement Handle Variable Evaluation, and What Workarounds Exist for Unexpected Behavior?

Klärung der Verwendung aufschieben

Beim Aufschieben einer Funktionsausführung in Go ist es wichtig, das Auswertungsverhalten zu verstehen. Wie in der Spezifikation angegeben, werden die Parameter und der Wert der Funktion sofort ausgewertet, wenn die Defer-Anweisung auftritt. Dies kann zu unerwarteten Ergebnissen führen, insbesondere wenn „defer“ mit Variablen verwendet wird, die innerhalb der Funktion geändert werden.

Der problematische Fall

Betrachten Sie die folgende Funktion:

func printNumbers() {
    var x int
    defer fmt.Println(x)

    for i := 0; i < 5; i++ {
        x++
    }
}

Die Die Absicht dieser Funktion besteht darin, den Endwert von x (5) auszugeben, wenn die Funktionsausführung endet. Aufgrund der sofortigen Auswertung von x während der Defer-Anweisung wird jedoch stattdessen Null gedruckt.

Alternative Lösungen

Um dieses Problem zu beheben, gibt es mehrere alternative Lösungen:

1. Anonyme Funktion:

Anstatt die ursprüngliche Funktion aufzuschieben, erstellen Sie eine anonyme Funktion, die den aktuellen Wert von x erfasst und ausgibt.

func printNumbers() {
    var x int
    defer func() { fmt.Println(x) }()

    for i := 0; i < 5; i++ {
        x++
    }
}

2. Zeiger:

Verwenden Sie einen Zeiger auf x, um den tatsächlichen Wert zu verschieben. Da bei der Defer-Anweisung nur die Adresse ausgewertet wird, wird der Endwert von x gedruckt.

func printNumbers() {
    var x int
    defer fmt.Println(&x)

    for i := 0; i < 5; i++ {
        x++
    }
}

func Print(i *int) {
    fmt.Println(*i)
}

3. Benutzerdefinierter Typ:

Erstellen Sie einen benutzerdefinierten Typ, der fmt.Stringer implementiert. Dadurch kann der Typ definieren, wie er gedruckt werden soll, um sicherzustellen, dass der richtige Wert angezeigt wird.

type MyInt int

func (m *MyInt) String() string {
    return strconv.Itoa(int(*m))
}

func printNumbers() {
    var x MyInt
    defer fmt.Println(&x)

    for i := 0; i < 5; i++ {
        x++
    }
}

4. Slices:

Slices sind Deskriptoren, die auf die zugrunde liegende Datenstruktur verweisen. Durch das Zurückstellen eines Slice, das die Variable enthält, wird der endgültige geänderte Wert gedruckt.

func printNumbers() {
    x := []int{0}
    defer fmt.Println(x)

    for i := 0; i < 5; i++ {
        x[0]++
    }
}

Fazit

Das Verständnis des unmittelbaren Auswertungsverhaltens verzögerter Funktionsausführungen ist für die effektive Verwendung von defer von entscheidender Bedeutung. Die bereitgestellten Lösungen zeigen verschiedene Ansätze, um sicherzustellen, dass die beabsichtigten Werte gedruckt werden, wenn die Ausführung einer Funktion verzögert wird.

Das obige ist der detaillierte Inhalt vonWie geht die „defer'-Anweisung von Go mit der Variablenauswertung um und welche Problemumgehungen gibt es für unerwartetes Verhalten?. 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