php-Editor Strawberry stellt Ihnen in diesem Artikel das Endlosschleifenproblem von io.Reader und fmt.Fscan vor. Wenn Sie die Funktion fmt.Fscan zum Lesen von Eingaben verwenden und der gelesene Inhalt nicht mit dem Eingabeformat übereinstimmt, kommt es zu einer Endlosschleife. Dieses Problem kann uns viel Ärger bereiten, aber mit ein paar Tipps und Vorsichtsmaßnahmen können wir es leicht lösen. Als Nächstes erklären wir ausführlich, wie Sie Endlosschleifen in io.Reader und fmt.Fscan vermeiden, damit Sie diese beiden Funktionen besser nutzen können.
Ich weiß nicht warum, aber meine io.reader
Implementierung scheint einen Fehler zu haben?
io.reader
heißt es, dass die Rückgabe einer Byteanzahl ungleich Null und eines Fehlers ungleich Null in Ordnung sein sollte:
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.
Aber das funktioniert nicht für fmt.fscan
und stattdessen hängt das Programm:
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) }
Natürlich, wenn ich io.eof
allein verwende, wird die Byteanzahl Null zurückgegeben:
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) }
Gibt es einen Fehler in meiner ursprünglichen Implementierung oder sollte ich mich nicht auf dieses spezielle Protokollierungsverhalten von io.reader
的这一特定记录行为,并且在没有更多数据可供读取时始终单独返回 0, io.eof
?
fmt.scanf
确实正确处理返回计数和 io.eof
,但即使在 io.eof
verlassen und immer nur 0, io.eof
zurückgeben, wenn keine Daten mehr zum Lesen vorhanden sind?
io.readfull
,而后者使用 io.readatleast
,因此您将需要一个更完整的实现来处理重复读取。您可以通过使用跟踪 eof 的扩展版本来测试这一点,并在第一个 read
上返回 io.eof
,它仍然可以按预期与 fmt.fscan
fmt.scanf
verarbeitet Rückgabezählungen und
weiterhin Werte zurück.
Da die Scanner-Implementierung auf der Verwendung von io.readfull
basiert, das
beim ersten Lesen
verfolgt und zurückgibt und weiterhin wie erwartet mit
io.readatleast
Wichtige Auszüge aus der Dokumentation:
io
帮助程序需要自己解释 io.eof
,所以它们的调用者只能查找返回的实际数据,并且由于您的阅读器继续返回数据,它们将无限期地重复调用。通过在阅读器上重复调用 io.readall
...es behandelt eof in read nicht als zu meldenden Fehler
io
-Helfer sich selbst interpretieren 🎜 müssen, können ihre Aufrufer nur die tatsächlich zurückgegebenen Daten nachschlagen, und da Ihr Reader weiterhin Daten zurückgibt, werden sie auf unbestimmte Zeit wiederholt aufgerufen. Dies kann leicht demonstriert werden, indem io.readall
wiederholt auf dem Reader aufgerufen wird und jedes Mal ein anderer Wert zurückgegeben wird. 🎜
b := Byte('9') fmt.Println(io.ReadAll(b)) fmt.Println(io.ReadAll(b)) fmt.Println(io.ReadAll(b)) // [57] <nil> // [57] <nil> // [57] <nil>
Das obige ist der detaillierte Inhalt vonio.Reader und fmt.Fscan Endlosschleife. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!