L'éditeur PHP Zimo vous présentera comment s'assurer que l'annulation du contexte entraînera la fin de la goroutine. Lorsque nous utilisons goroutine, nous devons parfois l'annuler lorsqu'une certaine condition est remplie pour éviter des calculs inutiles et un gaspillage de ressources. Pour garantir que la goroutine se termine correctement, nous pouvons utiliser le mécanisme fourni par le package de contexte. Le package de contexte fournit un moyen de transmettre les requêtes entre les goroutines et d'annuler ces requêtes en cas de besoin. En utilisant le package de contexte de manière appropriée, nous pouvons garantir que la goroutine se termine correctement lorsque le contexte est annulé, évitant ainsi les fuites de ressources et autres problèmes potentiels. Ci-dessous, nous détaillerons comment utiliser le package contextuel pour atteindre cet objectif.
Supposons que ce qui suit se produise :
Nous avons la consumer
fonction suivante, exécutée dans une goroutine.
Une autre goroutine est en ligne intchan
通道上毫无延迟地发送整数。换句话说,在 for 循环的每次迭代中,intchan
toutes deux avec une valeur prête à recevoir.
La goroutine qui a démarré la consumer
goroutine 的 goroutine 已取消传递到 consumer
的上下文。因此,ctx.done()
goroutine a annulé le contexte transmis à
ctx.done()
a également une valeur à recevoir. Question :
select
Selon le voyage de départ, select
不会继续选择 <- intchan
案例?如果 <- ctx.done()
案例在 for 循环的每次迭代中都准备就绪,我们如何知道 <- ctx.done()
Comment s'assurer que <- intchan
? Si le cas <- ctx.done()
est prêt à chaque itération de la boucle for, comment savons-nous que <- ctx.done() Les cas seront-ils éventuellement sélectionnés ?
func consumer(ctx context.context, intchan chan int) { for { select { case <-ctx.done(): return case i := <-intchan: foo(i) } } }
consumer
J'ai essayé d'utiliser la fonction consumer
和 producer
dans le programme ci-dessous.
Dans plusieurs exécutions de ce programme, les goroutines et producteur
semblent toujours se terminer.
<-ctx.done()
Pourquoi ne pas se retrouver avec une
package main import ( "context" "fmt" "sync" "time" ) func main() { ctx, cancelFunc := context.WithCancel(context.Background()) var wg sync.WaitGroup wg.Add(2) // add 2, because we spawn 2 goroutines Producer(ctx, &wg) fmt.Println(time.Now()) time.Sleep(time.Second * 5) // cancel the context after 5 seconds cancelFunc() fmt.Println("CANCELLED") wg.Wait() // wait till both producer and consumer goroutines terminate fmt.Println(time.Now()) } func Producer(ctx context.Context, wg *sync.WaitGroup) { intChan := make(chan int) go Consumer(ctx, intChan, wg) go func() { defer wg.Done() for { select { case <-ctx.Done(): return case intChan <- 1: } } }() } func Consumer(ctx context.Context, intChan chan int, wg *sync.WaitGroup) { defer wg.Done() for { select { case <-ctx.Done(): return case _ = <-intChan: } } }
ctx.err()
Aucune garantie. Le moyen le plus simple de garantir la résiliation est d'utiliser
func Consumer(ctx context.Context, intChan chan int) error { for ctx.Err() == nil { select { case <-ctx.Done(): case i := <-intChan: foo(i) } } return ctx.Err() }
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!