Maison  >  Article  >  développement back-end  >  Pourquoi mon programme Go n'utilise-t-il pas correctement la bibliothèque Contexte ?

Pourquoi mon programme Go n'utilise-t-il pas correctement la bibliothèque Contexte ?

WBOY
WBOYoriginal
2023-06-09 18:06:151316parcourir

Le langage Go est un excellent langage de programmation pour la programmation simultanée. L'utilisation simultanée des programmes Go est généralement implémentée à l'aide de coroutines et de canaux. Dans le langage Go, la bibliothèque Context est largement utilisée pour contrôler le cycle de vie et les opérations d'annulation des coroutines.

Cependant, nous rencontrons parfois des problèmes. Par exemple, notre programme Go ne peut pas utiliser correctement la bibliothèque Context, ce qui entraîne un fonctionnement anormal du programme. Alors pourquoi un tel problème se produit-il ? Cet article présentera en détail l'utilisation de la bibliothèque Context dans les programmes Go et les raisons qui peuvent empêcher l'utilisation correcte de la bibliothèque Context.

1. Qu'est-ce que la bibliothèque contextuelle ?

Tout d'abord, nous devons comprendre ce qu'est la bibliothèque Contexte. La bibliothèque Contexte est une bibliothèque standard introduite par le langage Go dans la version 1.7. Elle est utilisée pour transférer des informations de contexte entre coroutines afin de contrôler le comportement des coroutines lors du processus de transfert. La bibliothèque Context est principalement utilisée pour contrôler le cycle de vie des coroutines, fournir des chaînes de portée de requête, contrôler les délais d'attente et les opérations d'annulation, et fournir des informations de suivi et de journalisation, etc.

Lorsque vous utilisez Context, vous devez généralement créer un objet Context racine, puis utiliser cet objet pour créer des sous-Contextes, formant ainsi une arborescence de Context. En utilisant l'objet Contexte dans chaque coroutine, vous pouvez contrôler la coroutine. Si vous souhaitez annuler une coroutine, il vous suffit d'annuler l'objet Context de la coroutine correspondante.

2. Comment utiliser la bibliothèque Contexte ?

Normalement, l'utilisation de la bibliothèque Context est divisée selon les étapes suivantes :

  1. Créer un Context racine

Utilisez la fonction context.Background() pour créer un Context racine :

ctx := context.Background()
  1. Créez un sous-Contexte

Créé via le sous-contexte de contexte racine, utilisez la fonction context.WithValue() pour créer un sous-contexte :

ctx := context.Background()
ctx2 := context.WithValue(ctx, key, value)

Parmi eux, la clé et la valeur sont respectivement la clé et la valeur, utilisées pour stocker et transférer les informations de contexte. .

  1. Démarrez la coroutine

Utilisez le contexte à l'intérieur de la coroutine pour contrôler le comportement de la coroutine. Par exemple :

func hello(ctx context.Context) {
    select {
    case <-ctx.Done():
        return
    default:
        fmt.Println("Hello World!")
    }
}

func main() {
    ctx, cancel := context.WithCancel(context.Background())
    go hello(ctx)
    time.Sleep(1 * time.Second)
    cancel()
}

Dans le code ci-dessus, nous utilisons la fonction context.WithCancel() pour créer un sous-contexte avec opération d'annulation, puis transmettons ce sous-contexte à la coroutine dans la fonction hello() pour le contrôle. Dans la coroutine principale, utilisez la fonction Cancel() pour annuler le contexte correspondant, fermant ainsi la coroutine.

3. Problèmes courants avec la bibliothèque Context

Lors de l'utilisation de la bibliothèque Context, nous pouvons rencontrer les problèmes courants suivants :

  1. Une mauvaise utilisation de la fonction context.WithCancel() empêchera la coroutine de se fermer
func test(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            fmt.Println("End")
            return
        default:
            fmt.Println("Run...")
            time.Sleep(1 * time.Second)
        }
    }
}

func main() {
    ctx, cancel := context.WithCancel(context.Background())
    go test(ctx)
    fmt.Println("Start...")
    time.Sleep(3 * time.Second)
    cancel()
    fmt.Println("Cancel...")
    time.Sleep(3 * time.Second)
    fmt.Println("End...")
}

Dans le code ci-dessus, nous utilisons une instruction de boucle pour afficher en continu Run... dans une sous-coroutine. L'exécution de la fonction Cancel() dans la coroutine principale peut amener la sous-coroutine à mettre fin à la sortie de la boucle. Cependant, lorsque nous définissons le délai d'attente avant Cancel(), par exemple en utilisant :

go func() {
    time.Sleep(2 * time.Second)
    cancel()
}()

À ce moment, le code que nous attendons devrait être qu'après 2 secondes, la sous-coroutine arrête de produire Run..., puis génère End, et puis parce que la coroutine principale L'opération de mise en veille du programme fait attendre statiquement le programme pendant 3 secondes, et génère finalement End.. Mais en fait, le résultat de sortie de ce code est :

Start...
Run...
Run...
Cancel...
End...
Run...
Run...
Run...

C'est-à-dire que la sous-coroutine n'a pas quitté la boucle à temps, mais a arrêté de produire Run... après avoir attendu 2 secondes. En effet, après avoir défini le délai d'expiration, la coroutine principale n'aura peut-être pas la possibilité d'annuler la sous-coroutine après la sortie, mais attendra que la sous-coroutine se termine d'elle-même ou pendant le délai d'attente avant de quitter.

La façon de résoudre ce problème consiste à utiliser l'instruction select pour surveiller simultanément les appels d'annulation et d'expiration afin de garantir que la sous-coroutine peut être quittée à temps.

  1. Lors de l'utilisation de Context pour transférer des informations, il peut y avoir un problème de fuite d'informations

Lorsque Context transfère des informations de contexte, nous utilisons généralement des paires clé-valeur pour les transférer, telles que :

ctx := context.WithValue(context.Background(), "key", "value")

Cependant, lorsque nous utilisons Context pour Lors du transfert d'informations, des informations sensibles peuvent être transmises à d'autres parties de la coroutine, entraînant une fuite d'informations. Par conséquent, lorsque nous utilisons Context pour transférer des informations contextuelles, nous devons accorder une attention particulière à la protection des informations sensibles afin d'éviter les fuites d'informations.

4. Résumé

Pour résumer, la bibliothèque Context est une bibliothèque standard très importante dans le langage Go. Elle est utilisée pour transférer des informations de contexte entre les coroutines pour contrôler le comportement des coroutines. Lors de l'utilisation de la bibliothèque Context, nous devons faire attention à la façon dont le contexte est créé et utilisé, en particulier lors de la sortie de la coroutine et de la transmission des informations contextuelles. Nous devons faire attention pour éviter certains problèmes courants, tels que les fuites d'informations. Ce n'est qu'ainsi que nous pourrons utiliser la bibliothèque Context correctement et efficacement dans les programmes Go.

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