Bagaimana untuk mencipta konteks menggunakan tamat masa dan cuba semula dalam Go?

PHPz
Lepaskan: 2024-02-08 23:20:19
ke hadapan
687 orang telah melayarinya

如何在 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.

Kandungan soalan

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
            }
        }
    }
}
Salin selepas log masuk

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
Salin selepas log masuk

Penyelesaian

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 pembaca dan saluran untuk membaca daripada menggunakan 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!

Label berkaitan:
sumber:stackoverflow.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!