Contexte coroutine de Golang

Prenez l'habitude d'écrire ensemble ! C'est le 9ème jour de ma participation au "Nuggets Daily New Plan · April Update Challenge", cliquez pour voir les détails de l'événement .

aller dans le contexte coroutinecontext

golang est contextprincipalement utilisé pour transférer des informations de contexte entre les goroutines, notamment : le signal d'annulation, le délai d'attente, la date limite, le kv, etc.

contextC'est une fonctionnalité qui est sortie après la 1.17version golang

Problèmes résolus par le contexte

  1. Communication entre coroutines

Par exemple, dans une application Web, chaque requête est gérée par une coroutine. Bien sûr, pour cette coroutine qui traite les requêtes, nous démarrons généralement d'autres coroutines pour gérer d'autres services, tels que les opérations de base de données, l'authentification, la lecture et l'écriture de fichiers, etc. Ces coroutines sont indépendantes et nous ne pouvons pas percevoir comment les autres coroutines s'exécutent dans la coroutine actuelle. Le canal utilitaire channelpeut réaliser la fonction de communication

contextEssentiellement context.WithValue(), channella communication passe également par

  1. Gestion du timeout des sous-coroutines

De même, dans les applications Web, notre processus principal réside toujours en mémoire. Chaque demande est traitée par une coroutine. Dans le processus de traitement des affaires, une autre coroutine peut être démarrée pour traiter d'autres services. Lorsque la sous-coroutine est anormale ou bloquée, il est impossible de remonter les informations à la coroutine de niveau supérieur. , la coroutine principale se bloquera si elle ne reçoit pas de retour. Le contexte peut très bien résoudre ce problème, et contextpeut réaliser le timeout ou la sortie temporelle de la sous-coroutine ou de la coroutine descendante

Plusieurs méthodes et usages du contexte

context.WithCancel(context.Context)

WithCancel()La méthode passe dans une instance de contexte vide, qui peut être utilisée directement context.Background(), et renvoie un contexte et une fonction d'annulation. L' appel cancal()transmettra des signaux à d'autres coroutines, et les sous-coroutines peuvent être fermées ou traitées après avoir reçu le signal

package main
​
import (
    "context"
    "fmt"
    "time"
)
func worker(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            return
        default:
        }
        fmt.Println("worker...")
        time.Sleep(time.Second * 1)
    }
}
func main() {
    ctx, cancal := context.WithCancel(context.Background())
    go worker(ctx)
    time.Sleep(time.Second * 5)
    cancal()
    fmt.Println("over ...")
​
}
​
复制代码

context.WithTimeout(context.Context,timeout)

Définissez un contexte qui expirera. Après l'instanciation, le compte à rebours commencera. Le moment venu, la cancel()fonction sera automatiquement appelée pour notifier la sous-coroutine, ou la cancel()notification peut être appelée manuellement. S'il y a des sous-coroutines dans la sous-coroutine, continuez à utiliser ce contexte, lorsque la coroutine principale envoie un signal d'annulation, tous ceux qui utilisent ce contexte seront notifiés

package main
​
import (
    "context"
    "fmt"
    "time"
)
​
func worker(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            return
        default:
        }
        fmt.Println("worker...")
        time.Sleep(time.Second * 1)
    }
}
​
func main() {
    ctx, cancal := context.WithTimeout(context.Background(), time.Second*2)
    go worker(ctx)
    time.Sleep(time.Second * 5)
    cancal()
    fmt.Println("over ...")
​
}
​
复制代码

context.WithDeadline(context.Context,(绝对时间)timeout)

Définissez un contexte qui expirera, la Timeoutdifférence est que le temps passé est un temps absolu. Lorsque l'heure spécifiée est atteinte, la cancel()fonction sera automatiquement appelée pour notifier la sous-coroutine, ou la cancel()notification peut être appelée manuellement. S'il y a des sous-coroutines dans la sous-coroutine, continuez à utiliser ce contexte, lorsque la coroutine principale envoie un signal d'annulation, tous ceux qui utilisent ce contexte seront notifiés

package main
​
import (
    "context"
    "fmt"
    "time"
)
​
func worker(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            return
        default:
        }
        fmt.Println("worker...")
        time.Sleep(time.Second * 1)
    }
}
​
func main() {
    ctx, cancal := context.WithDeadline(context.Background(), time.Now().Add(3 * time.Second))
    go worker(ctx)
    time.Sleep(time.Second * 5)
    cancal()
    fmt.Println("over ...")
​
}
​
复制代码

Communication de contexte entre coroutines :context.WithValue()

Jetez d'abord un coup d'œil à ce code

package main
​
import (
    "context"
    "fmt"
    "time"
)
​
type CTXKEY string
​
func worker(ctx context.Context) {
    // 在子协程中获取上下文信息
    num, ok := ctx.Value(CTXKEY("num")).(string)
    if !ok {
        fmt.Println("invalid trace code")
    }
    fmt.Println(num)
    for {
        select {
        case <-ctx.Done():
            return
        default:
        }
        fmt.Println("worker...")
        time.Sleep(time.Second * 1)
    }
}
​
func main() {
    ctx, cancal := context.WithDeadline(context.Background(), time.Now().Add(3*time.Second))
    // 利用上下文传一个 num = 1234567
    // 实例化一个上下文
    ctx = context.WithValue(ctx, CTXKEY("num"), "1234567")
    go worker(ctx)
    time.Sleep(time.Second * 5)
    cancal()
    fmt.Println("over ...")
}
​
复制代码

La communication entre coroutines se fait par le biais du contexte Si le projet est important, afin d'éviter la pollution des variables, en principe : la clé utilisée pour la communication du contexte doit personnaliser un type

type traceCode string;context.WithValue(context.Context,key,value)

Je suppose que tu aimes

Origine juejin.im/post/7084613288104820773
conseillé
Classement