Maison >développement back-end >Golang >Introduction au go defer (fonction go delay)

Introduction au go defer (fonction go delay)

尚
avant
2019-11-30 14:03:382335parcourir

Le report du langage Go

Introduction au go defer (fonction go delay)

Go est considéré comme une nouvelle fonctionnalité du langage, du moins par rapport aux langages de programmation traditionnels d'aujourd'hui.

L'instruction defer appelle une fonction. L'exécution de cette fonction sera reportée jusqu'au retour de la fonction périphérique, ou jusqu'à la fin de la fonction périphérique, ou jusqu'à ce que la goroutine correspondante panique

Chaque fois que defer est utilisé. exécuté, il La valeur de la fonction suivante (dans Go, la fonction est un type de référence, un citoyen de première classe et peut être affectée à une variable) et les paramètres de la fonction seront évalués, mais la fonction ne sera appelée immédiatement que (↑ ), les trois situations ci-dessus se produisent. C'est tout le contenu de defer, disparu, le reste est la meilleure pratique de defer

La fonction ne sera pas appelée immédiatement

Commençons par la plus simple :

func readFile(fileName string){
    f,err := os.Open(fileName)
    if err!=nil {
        return
    }
    defer f.Close()
    var content [1024]byte
    f.Read(content[:])
    fmt.Printf("%s",content)
}
func main() {
    readFile("test.data")
}

Le programme génère les 1024 premiers octets de test.data. Il convient de mentionner que les opérations de couplage ouverture/fermeture comme celle-ci sont l'usage idiomatique du report. Cet exemple explique la seconde moitié de la phrase ci-dessus

"Mais la fonction ne sera pas appelée"

Parce que si f.Close() après le defer n'est pas retardé, alors le descripteur de fichier S'ils sont tous fermés, rien ne sera lu.

La valeur de la fonction et les paramètres de la fonction sont évalués, mais la fonction n'est pas appelée immédiatement

L'exemple suivant expliquera la première moitié, il vient de a8093152e673feb7aba1828c43532094 , légèrement Modification :

func trace(funcName string) func(){
    start := time.Now()
    fmt.Printf("function %s enter\n",funcName)
    return func(){
        log.Printf("function %s exit (elapsed %s)",funcName,time.Since(start))
    }
}
 
func foo(){
    defer trace("foo()")()
    time.Sleep(5*time.Second)
}
func main(){
    foo()
    foo()
}
/*
OUTPUT:
function foo() enter
function foo() exit (elapsed 5.0095471s)
function foo() enter
function foo() exit (elapsed 5.0005382s)
*/

Pourquoi la sortie foo entre-t-elle puis attend-elle environ cinq secondes avant de sortir la sortie Parce que comme nous l'avons dit, les valeurs et les paramètres de la fonction après

defer seront évalués ? mais la fonction réelle L'appel doit attendre la fin

La valeur de la fonction ici est la fonction anonyme renvoyée par trace(). Le paramètre de la fonction est bien sûr la valeur littérale de la chaîne "foo()". de trace("foo()") la fonction de sortie foo() entrera, l'appel de fonction réel trace("foo()")(), c'est-à-dire que la fonction de sortie foo() exit(elapsed x.x) sera reportée à return exécution (si return mettra à jour la variable de valeur de retour, elle sera exécutée après la mise à jour avant d'exécuter la fonction defer).

Divers

Un petit plus, s'il y a plusieurs instructions defer, l'ordre d'exécution de la dernière fonction defer est opposé à l'ordre dans lequel defer apparaît, comme par exemple :

func main() {
    func1 := func(){
        fmt.Println("func1() execution deferred")
    }
    func2 := func(){
        fmt.Println("func2() execution deferred")
    }
    defer func1()
    defer func2()
    fmt.Println("strat\nworking...")
}
/*
OUTPUT:
strat
working...
func2() execution deferred
func1() execution deferred
*/

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:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer