l'éditeur php Xinyi vous présentera comment utiliser le délai d'attente et réessayer pour créer un contexte en langage Go. Lors de l'écriture de code, nous rencontrons souvent des situations dans lesquelles nous devons limiter le temps d'exécution d'une opération ou réessayer lorsque l'opération échoue. Le langage Go fournit un mécanisme simple et puissant, un contexte, qui peut nous aider à répondre à ces besoins. En utilisant correctement les mécanismes de délai d'attente et de nouvelle tentative, nous pouvons améliorer la fiabilité et la stabilité du code tout en améliorant l'expérience utilisateur. Dans le prochain article, nous verrons en détail comment utiliser les délais d'attente et les tentatives pour créer un contexte en langage Go.
J'essaie de créer un contexte en cours d'exécution en utilisant un délai d'attente et plusieurs tentatives. Voici l'exemple de code
func readretry(port io.readwritecloser, timeout, cnt int) []byte { fmt.println("in read retry") for i := 0; i < cnt; i++ { fmt.println("read attempt:", i) res := readwithcontext(timeout, port) if res != nil { return res } } return nil } func readwithcontext(timeout int, port io.readwritecloser) []byte { fmt.println("in readwithcontext") fmt.println("opening channel") rcvch := make(chan []byte) ctx, cancel := context.withtimeout(context.background(), time.duration(time.second*time.duration(timeout))) defer cancel() go reader(ctx, port, rcvch) for { select { case <-ctx.done(): fmt.println("reader: context cancelled") return nil case buf := <-rcvch: fmt.println("reader: got data") return buf } } } func reader(ctx context.context, port io.readwritecloser, rcvch chan []byte) { fmt.println("in reader") answ := make([]byte, 1024) buf := bytes.buffer{} var err error for { i := 0 i, err = port.read(answ) if err != nil && err != io.eof { log.printf("port.read: %v", err) } if i != 0 { answ = answ[:i] buf.write(answ) if buf.bytes()[len(buf.bytes())-1] == delimiter { fmt.print("received: ") printbuf(buf.bytes()) rcvch <- buf.bytes() //if there is no data in the first attempt, cannot write to the channel here!! return } } } }
Ensuite, j'appelle readretry result := readretry(port, 2, 5) // 2 secondes d'attente, 5 tentatives. Mais si les données ne sont pas prêtes la première fois, alors reader ne peut pas écrire sur rcvch . Peut-être qu'il est plein ? Pourquoi? Si j'essaie de fermer le canal à la fin de l'exécution de readwithcontext, un conflit se produit : l'écriture sur un canal fermé. Où est la collision ? Il pense que readwithcontext sera démarré comme une nouvelle instance à chaque fois, créant une nouvelle instance de rcvch, et si reader est fermé en raison d'un délai d'attente, toutes les fonctions de la chaîne et leurs variables locales (y compris les canaux) ont été détruites . Cependant, il semble que j'ai commis une erreur. Alors, comment réessayer ? Voyez à quoi ressemble le journal :
IN READ RETRY Read attempt: 1 IN readWithContext Opening channel IN reader Start reader Received: 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0d //<- data is received, but not written to the channel!! reader: context cancelled
Chaque nouvelle tentative créera un nouveau lecteur et une nouvelle chaîne. Si readWithContext
expire, le lecteur attend toujours et peut éventuellement lire, mais maintenant personne n'écoute à l'autre bout du canal, donc le lecteur est divulgué.
Il existe une goroutine reader
et un canal pour lire à partir de l'utilisation reader
goroutine 和一个通道,使用 readWithContext
. Vous devez également arrêter le lecteur si le contexte expire et que toutes les tentatives sont épuisées.
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!