Maison  >  Article  >  développement back-end  >  Appeler defer dans une boucle for - existe-t-il un meilleur moyen de retarder la lecture de la réponse du canal ?

Appeler defer dans une boucle for - existe-t-il un meilleur moyen de retarder la lecture de la réponse du canal ?

王林
王林avant
2024-02-09 12:15:221169parcourir

在 for 循环中调用 defer - 是否有更好的方法来延迟从通道读取响应?

Call différé dans une boucle for - existe-t-il un meilleur moyen de retarder la lecture de la réponse du canal ? Il s'agit d'un problème courant que de nombreux développeurs rencontrent lorsqu'ils utilisent le langage Go. Le mot-clé defer est utilisé pour retarder l'exécution des fonctions dans le langage Go. L'utilisation de defer dans une boucle for peut garantir que certaines opérations sont effectuées après la fin de chaque boucle. Cependant, si vous devez lire la réponse du canal à chaque boucle, l'utilisation du report n'est peut-être pas le meilleur choix. Alors, existe-t-il un meilleur moyen de retarder la lecture de la réponse du canal ? Explorons-le ensemble.

Contenu de la question

J'essaie d'appeler une fonction qui renvoie un canal en boucle. Ajoutez ensuite ce canal à la tranche channelslice. Enfin, parcourez les tranches de canal et imprimez la réponse pour chaque canal. Lorsque je fais cela, mon IDE affiche l'avertissement :

possible resource leak, 'defer' is called in the 'for' loop

Comme vous pouvez le voir, j'appelle close(channelslice[i]) à l'intérieur de la seconde boucle for. N'est-ce pas recommandé ? De plus, comment cela pourrait-il provoquer une fuite de ressources ? Existe-t-il une meilleure façon de gérer la fermeture ou le découpage des canaux ?

package main


import (
    "fmt"
    "math/rand"
)

func t() chan int {
    c := make(chan int)
    go func() {
        c <- rand.Intn(100)
    }()

    return c
}

func main() {
    channelSlice := make([]chan int, 0)
    for i := 0; i<100; i++ {
        // Keep making concurrent calls
        // Will read responses from the channel later
        channelSlice = append(channelSlice, t())
    }

    for i := 0; i<100; i++ {
        defer close(channelSlice[i]) // Warning thrown by IDE
        fmt.Println(<-channelSlice[i])
    }
}

Solution de contournement

Comme @mkopriva l'a souligné,

Les appels retardés sont exécutés à la sortie des fonctions environnantes, ils ne sont pas appelés à la sortie des blocs non fonctionnels environnants. Encapsulez le corps de la boucle dans une fermeture.

Voici ce que j'ai fait :

for i := 0; i<100; i++ {
        func() {
            defer close(channelSlice[i])
            fmt.Println(<-channelSlice[i])
        }()
    }

Comme vous pouvez le voir, j'ai enveloppé l'instruction defer dans un iife (expression de fonction immédiatement invoquée). Ce serait aussi bien d’en faire une fermeture.

Cela garantit que le canal sera désormais fermé et qu'aucune fuite de mémoire ne se produira.

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