Maison >développement back-end >Golang >Boucle infinie io.Reader et fmt.Fscan
l'éditeur php Strawberry vous présentera le problème de boucle infinie de io.Reader et fmt.Fscan dans cet article. Lorsque vous utilisez la fonction fmt.Fscan pour lire une entrée, si le contenu lu ne correspond pas au format d'entrée, une boucle infinie se produira. Ce problème peut nous causer beaucoup de problèmes, mais avec quelques conseils et précautions, nous pouvons facilement résoudre ce problème. Ensuite, nous expliquerons en détail comment éviter les boucles infinies dans io.Reader et fmt.Fscan pour vous aider à mieux utiliser ces deux fonctions.
Je ne sais pas pourquoi, mais ma io.reader
implémentation semble avoir une sorte de défaut ?
io.reader
indique que renvoyer un nombre d'octets différent de zéro et une erreur non nulle devrait convenir :
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.
Mais cela ne fonctionne pas pour fmt.fscan
et bloque le programme :
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) }
Bien sûr, si j'utilise io.eof
seul, il renvoie zéro nombre d'octets :
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) }
Y a-t-il un défaut dans mon implémentation d'origine ou ne dois-je pas me fier à ce comportement de journalisation spécifique de io.reader
的这一特定记录行为,并且在没有更多数据可供读取时始终单独返回 0, io.eof
?
fmt.scanf
确实正确处理返回计数和 io.eof
,但即使在 io.eof
et renvoyer toujours 0, io.eof
seul lorsqu'il n'y a plus de données à lire ?
io.readfull
,而后者使用 io.readatleast
,因此您将需要一个更完整的实现来处理重复读取。您可以通过使用跟踪 eof 的扩展版本来测试这一点,并在第一个 read
上返回 io.eof
,它仍然可以按预期与 fmt.fscan
fmt.scanf
gère correctement le nombre de retours et
.
Étant donné que l'implémentation du scanner repose sur l'utilisation de io.readfull
qui utilise
lors de la première lecture
et elle fonctionnera toujours avec
io.readatleast
Extraits clés de la documentation :
io
帮助程序需要自己解释 io.eof
,所以它们的调用者只能查找返回的实际数据,并且由于您的阅读器继续返回数据,它们将无限期地重复调用。通过在阅读器上重复调用 io.readall
...il ne traite pas eof en lecture comme une erreur à signaler
io
doivent interpréter 🎜 eux-mêmes, leurs appelants ne peuvent rechercher que les données réelles renvoyées, et puisque votre lecteur continue de renvoyer des données, ils seront appelés à plusieurs reprises indéfiniment. Cela peut être facilement démontré en appelant io.readall
à plusieurs reprises sur le lecteur, renvoyant une autre valeur à chaque fois. 🎜
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🎜🎜
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!