Maison > développement back-end > Golang > Comment l'instruction « defer » de Go gère-t-elle l'évaluation des variables et quelles solutions de contournement existent en cas de comportement inattendu ?

Comment l'instruction « defer » de Go gère-t-elle l'évaluation des variables et quelles solutions de contournement existent en cas de comportement inattendu ?

Linda Hamilton
Libérer: 2024-12-18 13:32:15
original
283 Les gens l'ont consulté

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

Clarification de l'utilisation du report

Lors du report de l'exécution d'une fonction dans Go, il est crucial de comprendre le comportement d'évaluation. Comme indiqué dans la spécification, les paramètres et la valeur de la fonction sont immédiatement évalués lorsque l'instruction defer est rencontrée. Cela peut conduire à des résultats inattendus, en particulier lors de l'utilisation de defer avec des variables modifiées au sein de la fonction.

Le cas problématique

Considérez la fonction suivante :

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

    for i := 0; i < 5; i++ {
        x++
    }
}
Copier après la connexion

Le L'intention de cette fonction est d'imprimer la valeur finale de x (5) à la fin de l'exécution de la fonction. Cependant, en raison de l'évaluation immédiate de x lors de l'instruction différée, zéro sera imprimé à la place.

Solutions alternatives

Pour résoudre ce problème, plusieurs solutions alternatives existent :

1. Fonction anonyme :

Au lieu de différer la fonction d'origine, créez une fonction anonyme qui capture et imprime la valeur actuelle de x.

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

    for i := 0; i < 5; i++ {
        x++
    }
}
Copier après la connexion

2. Pointeur :

Utilisez un pointeur vers x pour différer la valeur réelle. Puisque seule l'adresse est évaluée lors de l'instruction différée, la valeur finale de x sera imprimée.

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

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

func Print(i *int) {
    fmt.Println(*i)
}
Copier après la connexion

3. Type personnalisé :

Créez un type personnalisé implémentant fmt.Stringer. Cela permet au type de définir comment il doit être imprimé, garantissant que la valeur correcte est affichée.

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++
    }
}
Copier après la connexion

4. Tranches :

Les tranches sont des descripteurs qui font référence à la structure de données sous-jacente. En différant une tranche qui contient la variable, la valeur finale modifiée sera imprimée.

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

    for i := 0; i < 5; i++ {
        x[0]++
    }
}
Copier après la connexion

Conclusion

Comprendre le comportement d'évaluation immédiat des exécutions de fonctions différées est essentiel pour utiliser efficacement le report. Les solutions fournies démontrent diverses approches pour garantir que les valeurs prévues sont imprimées lors du report de l'exécution d'une fonction.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal