Rumah  >  Artikel  >  pembangunan bahagian belakang  >  io.Reader dan fmt.Fscan gelung tak terhingga

io.Reader dan fmt.Fscan gelung tak terhingga

WBOY
WBOYke hadapan
2024-02-09 17:45:191184semak imbas

io.Reader 与 fmt.Fscan 无限循环

editor php Strawberry akan memperkenalkan kepada anda masalah gelung tak terhingga io.Reader dan fmt.Fscan dalam artikel ini. Apabila menggunakan fungsi fmt.Fscan untuk membaca input, jika kandungan yang dibaca tidak sepadan dengan format input, gelung tak terhingga akan berlaku. Masalah ini mungkin menyebabkan kita banyak masalah, tetapi dengan beberapa petua dan langkah berjaga-jaga, kita boleh menyelesaikan masalah ini dengan mudah. Seterusnya, kami akan menerangkan secara terperinci cara mengelakkan gelung tak terhingga dalam io.Reader dan fmt.Fscan untuk membantu anda menggunakan kedua-dua fungsi ini dengan lebih baik.

Kandungan soalan

Tidak tahu mengapa, tetapi pelaksanaan io.reader saya nampaknya mempunyai sedikit kecacatan?

Dokumentasi untuk

io.reader menyatakan bahawa mengembalikan kiraan bait bukan sifar dan ralat bukan sifar sepatutnya baik:

it may return the (non-nil) error from the same call or return the error (and n == 0) from a subsequent call. an instance of this general case is that a reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == nil. the next read should return 0, eof.
callers should always process the n > 0 bytes returned before considering the error err. doing so correctly handles i/o errors that happen after reading some bytes and also both of the allowed eof behaviors.

Tetapi ini tidak berfungsi untuk fmt.fscan dan sebaliknya menggantung program:

package main

import (
    "fmt"
    "io"
)

type byte byte

func (b byte) read(p []byte) (n int, err error) {
    if len(p) == 0 {
        return 0, io.errshortbuffer
    }
    p[0] = byte(b)
    return 1, io.eof
}

func main() {
    var n int
    b := byte('9')
    z, err := fmt.fscan(b, &n)
    fmt.println(n, z, err)
}

Sudah tentu, jika saya menggunakan io.eof sahaja ia mengembalikan kiraan bait sifar:

type Byte struct {
    v   byte
    eof bool
}

func (b *Byte) Read(p []byte) (n int, err error) {
    if len(p) == 0 {
        return 0, io.ErrShortBuffer
    }
    if b.eof {
        return 0, io.EOF
    }
    p[0] = b.v
    b.eof = true
    return 1, nil
}

func main() {
    var n int
    b := Byte{v: '9'}
    z, err := fmt.Fscan(&b, &n)
    fmt.Println(n, z, err)
}

Adakah terdapat kecacatan dalam pelaksanaan asal saya atau saya tidak patut bergantung pada gelagat pengelogan khusus ini io.reader 的这一特定记录行为,并且在没有更多数据可供读取时始终单独返回 0, io.eof

解决方法

fmt.scanf 确实正确处理返回计数和 io.eof,但即使在 io.eof dan sentiasa mengembalikan 0, io.eof sahaja apabila tiada lagi data untuk dibaca ?

Penyelesaian

io.readfull,而后者使用 io.readatleast,因此您将需要一个更完整的实现来处理重复读取。您可以通过使用跟踪 eof 的扩展版本来测试这一点,并在第一个 read 上返回 io.eof ,它仍然可以按预期与 fmt.fscanfmt.scanf mengendalikan kiraan pulangan dan

dengan betul, tetapi pembaca anda terus mengembalikan nilai walaupun selepas

.

Memandangkan pelaksanaan pengimbas bergantung pada penggunaan io.readfull yang menggunakan

, anda memerlukan pelaksanaan yang lebih lengkap untuk mengendalikan bacaan pendua. Anda boleh menguji ini dengan menggunakan versi lanjutan yang menjejaki eof dan mengembalikan

pada baca pertama dan ia masih akan berfungsi dengan

seperti yang diharapkan.

io.readatleastPetikan utama daripada dokumentasi:

io 帮助程序需要自己解释 io.eof ,所以它们的调用者只能查找返回的实际数据,并且由于您的阅读器继续返回数据,它们将无限期地重复调用。通过在阅读器上重复调用 io.readall...ia tidak menganggap eof dalam dibaca sebagai ralat untuk melaporkan

Ralat akan berlaku hanya jika tiada bait dibaca. 🎜 🎜Oleh kerana pembantu io ini perlu mentafsir 🎜 sendiri, pemanggil mereka hanya boleh mencari data sebenar yang dikembalikan dan memandangkan pembaca anda terus memulangkan data, mereka akan dipanggil berulang kali selama-lamanya. Ini boleh ditunjukkan dengan mudah dengan memanggil io.readall berulang kali pada pembaca, mengembalikan nilai lain setiap kali. 🎜
b := Byte('9')
fmt.Println(io.ReadAll(b))
fmt.Println(io.ReadAll(b))
fmt.Println(io.ReadAll(b))

// [57] <nil>
// [57] <nil>
// [57] <nil>
🎜🎜https://www.php.cn/link/ad6fff7b7be06acff1c63ced9f0da4ea🎜🎜

Atas ialah kandungan terperinci io.Reader dan fmt.Fscan gelung tak terhingga. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam