Rumah > Artikel > pembangunan bahagian belakang > Bagaimana untuk mencipta konteks menggunakan tamat masa dan cuba semula dalam Go?
editor php Xinyi akan memperkenalkan kepada anda cara menggunakan tamat masa dan cuba semula untuk mencipta konteks dalam bahasa Go. Apabila menulis kod, kita sering menghadapi situasi di mana kita perlu mengehadkan masa pelaksanaan operasi atau mencuba semula apabila operasi gagal. Bahasa Go menyediakan mekanisme, konteks yang mudah dan berkuasa, yang boleh membantu kami mencapai keperluan ini. Dengan menggunakan mekanisme tamat masa dan cuba semula dengan betul, kami boleh meningkatkan kebolehpercayaan dan kestabilan kod sambil meningkatkan pengalaman pengguna. Dalam artikel seterusnya, kami akan membincangkan secara terperinci cara menggunakan tamat masa dan cuba semula untuk mencipta konteks dalam bahasa Go.
Saya cuba mencipta konteks semasa pergi menggunakan tamat masa dan berbilang percubaan semula. Berikut ialah contoh kod
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 } } } }
Kemudian saya memanggil readretry hasil := readretry(port, 2, 5) // tamat masa 2 saat, 5 percubaan semula. Tetapi jika data tidak siap pada kali pertama, maka pembaca tidak boleh menulis kepada rcvch . Mungkin ia penuh? kenapa? Jika saya cuba menutup saluran pada penghujung pelaksanaan readwithcontext, konflik berlaku - menulis ke saluran tertutup. Di manakah perlanggaran? Ia berpendapat bahawa readwithcontext akan dimulakan sebagai tika baharu setiap kali, mencipta tika baharu rcvch, dan jika reader ditutup kerana tamat masa, semua fungsi rantai dan pembolehubah setempatnya (termasuk saluran) telah dimusnahkan . Namun, nampaknya saya melakukan kesilapan. Jadi, bagaimana untuk mencuba semula? Lihat rupa log itu:
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
Setiap percubaan semula akan mencipta pembaca baharu dan saluran baharu. Jika readWithContext
masa tamat, pembaca masih di sana menunggu, dan akhirnya boleh membaca, tetapi kini tiada siapa yang mendengar di hujung saluran, jadi pembaca bocor.
Terdapat goroutine reader
goroutine 和一个通道,使用 readWithContext
. Anda juga mesti menghentikan pembaca jika konteks tamat tempoh dan semua percubaan semula telah habis.
Atas ialah kandungan terperinci Bagaimana untuk mencipta konteks menggunakan tamat masa dan cuba semula dalam Go?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!