Maison  >  Article  >  développement back-end  >  Pourquoi `defer func() { fmt.Println(i) }()` imprime '44444' dans Go, alors que `defer func(n int) { fmt.Println(n) }(i)` imprime correctement '43210' ?

Pourquoi `defer func() { fmt.Println(i) }()` imprime '44444' dans Go, alors que `defer func(n int) { fmt.Println(n) }(i)` imprime correctement '43210' ?

DDD
DDDoriginal
2024-11-10 18:54:02456parcourir

Why does `defer func() { fmt.Println(i) }()` print

Appels de fonction différés et capture de fermeture

Dans Go, l'instruction defer nous permet d'exécuter une fonction juste avant le retour de la fonction environnante. Un aspect important de Defer est la façon dont il gère les fermetures.

Dans cet extrait de code :

package main

import "fmt"

func main() {
    var whatever [5]struct{}

    for i := range whatever {
        fmt.Println(i)
    } // part 1

    for i := range whatever {
        defer func() { fmt.Println(i) }()  // part 2
    }

    for i := range whatever {
        defer func(n int) { fmt.Println(n) }(i)  // part 3
    }
}

La partie 1 imprime simplement les valeurs de i de 0 à 4. La partie 2, cependant, démontre un comportement intéressant. Au lieu d'imprimer les valeurs attendues de 0 à 4, il affiche "44444".

En effet, la fermeture de la partie 2 capture la variable i. Lorsque la fermeture est exécutée plus tard, la variable i a la valeur qu'elle avait lors de la dernière itération de l'instruction range, qui est 4. Par conséquent, toutes les fonctions différées appellent print 4.

En revanche, une partie 3 ne capture aucune variable externe. Selon les spécifications Go, "chaque fois que l'instruction 'defer' s'exécute, la valeur de la fonction et les paramètres de l'appel sont évalués comme d'habitude et enregistrés à nouveau, mais la fonction réelle n'est pas invoquée." Cela signifie que chacun des appels de fonction différés a une valeur différente du paramètre « n », qui est la valeur de « i » au moment où l'instruction « defer » a été exécutée.

Par conséquent, la partie 3 est correcte. affiche "43210" car les appels de fonction différés sont exécutés dans l'ordre LIFO (dernier entré, premier sorti) avant le retour de la fonction environnante.

Il est crucial de se rappeler que l'expression de fonction dans 'defer f()' n'est pas exécuté au moment de l'exécution de l'instruction defer, tandis que l'expression dans 'defer f(e)' est évaluée immédiatement.

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!

Déclaration:
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