Go-Quellcode-Lernen: bufio package-1.1-bufio.go-(2)

Offizielle Dokumentation des Bufio-Pakets

Gehen Sie zum Quellcode-Learning-Index-Verzeichnis

Vorheriger Artikel zum Lernen von Bufio-Paketen: Go-Quellcode-Lernen: bufio package-1.1-bufio.go-(1)

7. Lesen: Daten lesen

// Read 读取数据到 p 中。
// 它返回读取到 p 中的字节数。
// 这些字节最多来自底层 [Reader] 的一次读取,
// 因此 n 可能小于 len(p)。
// 要精确读取 len(p) 字节,请使用 io.ReadFull(b, p)。
// 如果底层 [Reader] 可以在 io.EOF 时返回非零计数,
// 则此 Read 方法也可以这样做;参见 [io.Reader] 文档。
func (b *Reader) Read(p []byte) (n int, err error) {
    
    
	n = len(p)
	if n == 0 {
    
    
		if b.Buffered() > 0 {
    
    
			return 0, nil
		}
		return 0, b.readErr()
	}
	if b.r == b.w {
    
    
		if b.err != nil {
    
    
			return 0, b.readErr()
		}
		if len(p) >= len(b.buf) {
    
    
			// Large read, empty buffer.
			// Read directly into p to avoid copy.
			n, b.err = b.rd.Read(p)
			if n < 0 {
    
    
				panic(errNegativeRead)
			}
			if n > 0 {
    
    
				b.lastByte = int(p[n-1])
				b.lastRuneSize = -1
			}
			return n, b.readErr()
		}
		// One read.
		// Do not use b.fill, which will loop.
		b.r = 0
		b.w = 0
		n, b.err = b.rd.Read(b.buf)
		if n < 0 {
    
    
			panic(errNegativeRead)
		}
		if n == 0 {
    
    
			return 0, b.readErr()
		}
		b.w += n
	}

	// copy as much as we can
	// Note: if the slice panics here, it is probably because
	// the underlying reader returned a bad count. See issue 49795.
	n = copy(p, b.buf[b.r:b.w])
	b.r += n
	b.lastByte = int(b.buf[b.r-1])
	b.lastRuneSize = -1
	return n, nil
}

erklären:

  • ReadDie Methode ist Readereine Methode der Struktur und hat keinen expliziten Empfänger, sondern verwendet bdie Felder der Struktur.
  • Mit dieser Methode werden Daten in ein Slice eingelesen p.
  • Der Rückgabewert stellt die Anzahl der eingelesenen Bytes ndar .p
  • Wenn nder Wert Null ist und sich Daten im Puffer befinden, wird Null direkt zurückgegeben, was darauf hinweist, dass null Bytes erfolgreich gelesen wurden.
  • Wenn sich keine Daten im Puffer befinden, ermitteln Sie, ob Readerneue Daten aus der darunter liegenden Schicht gelesen werden müssen.
  • Wenn der Lesezeiger des Puffers b.rgleich dem Schreibzeiger ist b.w, bedeutet dies, dass der Puffer leer ist und ReaderDaten aus der unteren Ebene gelesen werden müssen.
    • Wenn ein Fehler vorliegt b.err, wird ein Lesefehler zurückgegeben.
    • Wenn pdie Länge des Slice größer oder gleich der Länge des Puffers ist len(b.buf), lesen Sie direkt, pum ein Zwischenkopieren zu vermeiden.
    • Andernfalls führen Sie einen Lesevorgang ohne Verwendung durch, b.fillum zirkuläre Aufrufe zu vermeiden.
  • Wenn sich Daten im Puffer befinden, verwenden Sie copydie Funktion, um so viele Daten wie möglich aus dem Puffer in das Slice zu kopieren p.
  • Aktualisieren Sie den Lesezeiger b.r, um die Größe des letzten Bytes und der letzten Rune aufzuzeichnen.
  • Gibt die tatsächliche Anzahl der gelesenen Bytes zurück n.

Wirkung:

  • ReadDie Methode wird verwendet, um Daten Readeraus .
  • Zuerst werden Daten aus dem Puffer gelesen. Wenn der Puffer leer ist, werden ReaderDaten aus dem zugrunde liegenden Puffer gelesen.
  • Diese Methode gibt die Anzahl der gelesenen Bytes und eventuell aufgetretene Fehler zurück.

8. ReadByte: Ein einzelnes Byte lesen

// ReadByte 读取并返回一个字节。
// 如果没有可用的字节,则返回错误。
func (b *Reader) ReadByte() (byte, error) {
    
    
    b.lastRuneSize = -1
    for b.r == b.w {
    
    
        if b.err != nil {
    
    
            return 0, b.readErr()
        }
        b.fill() // 缓冲区为空时填充
    }
    c := b.buf[b.r]
    b.r++
    b.lastByte = int(c)
    return c, nil
}

erklären:

  • ReadByteIst Readereine Methode einer Struktur, die ein Byte liest und zurückgibt.
  • Wenn im Puffer keine Bytes verfügbar sind, fillwird die Methode aufgerufen, um ihn zu füllen.
  • Die Schleife prüft b.r, ob der Lesezeiger gleich dem Schreibzeiger ist b.w. Bei Gleichheit ist der Puffer leer und muss gefüllt werden.
  • Wenn ein Fehler vorliegt b.err, wird ein Lesefehler zurückgegeben.
  • Liest ein Byte aus dem Puffer cund b.rverschiebt den Lesezeiger vorwärts.
  • Zeichnet den ganzzahligen Wert des letzten Bytes auf und gibt die gelesenen Bytes und nileinen Fehler zurück.

Wirkung:

  • ReadByteMit dieser Methode wird ein Byte aus dem Puffer gelesen.
  • Wenn der Puffer leer ist, wird er zuerst gefüllt.
  • Gibt die gelesenen Bytes und mögliche Fehler zurück.

9. UnreadByte: Machen Sie das zuletzt gelesene Byte rückgängig

// UnreadByte 撤销最近读取的字节。只有最近读取的字节可以被撤销。
//
// 如果最近调用 [Reader] 上的方法不是读取操作,则 UnreadByte 会返回错误。
// 特别地,[Reader.Peek]、[Reader.Discard] 和 [Reader.WriteTo] 不被认为是读取操作。
func (b *Reader) UnreadByte() error {
    
    
    // 如果最近的字节值为负值(表示未读取),或者读指针为0但写指针大于0(表示有未读取的数据),返回无效的撤销字节错误。
    if b.lastByte < 0 || b.r == 0 && b.w > 0 {
    
    
        return ErrInvalidUnreadByte
    }
    // 如果读指针大于0,表示有已读取的数据,将读指针前移一位。
    if b.r > 0 {
    
    
        b.r--
    } else {
    
    
        // 如果读指针为0且写指针为0,表示缓冲区为空,将写指针设置为1。
        b.w = 1
    }
    // 将最近读取的字节值写回缓冲区的读指针位置。
    b.buf[b.r] = byte(b.lastByte)
    // 重置最近读取的字节和最近 rune 大小的状态。
    b.lastByte = -1
    b.lastRuneSize = -1
    return nil
}

erklären:

  • UnreadByteMethode ist Readereine Methode der Struktur, mit der das zuletzt gelesene Byte rückgängig gemacht wird.
  • Überprüfen Sie zunächst, ob der letzte Bytewert negativ ist (was darauf hinweist, dass er nicht gelesen wurde) oder ob der Lesezeiger 0 ist, der Schreibzeiger jedoch größer als 0 ist (was darauf hinweist, dass ungelesene Daten vorhanden sind). Wenn ja, handelt es sich um ein ungültiges Rückgängig-Byte Es wird ein Fehler zurückgegeben.
  • Wenn der Lesezeiger größer als 0 ist, bedeutet dies, dass Daten gelesen wurden, und der Lesezeiger wird um ein Bit vorwärts verschoben. Andernfalls bedeutet dies, dass der Lesezeiger 0 und der Schreibzeiger 0 ist Der Puffer ist leer und der Schreibzeiger ist auf 1 gesetzt.
  • Schreibt den zuletzt gelesenen Bytewert zurück in den Puffer an der Lesezeigerposition.
  • Setzen Sie abschließend den Status der zuletzt gelesenen Bytes und der neuesten Runengröße zurück und geben Sie bei Erfolg Null zurück.

Wirkung:

  • UnreadByteDie Methode ermöglicht es, das zuletzt erfolgreich gelesene Byte rückgängig zu machen und den Lesezeiger nach vorne zu verschieben, sodass das Byte wieder verfügbar ist.
  • Diese Methode ist nützlich, wenn Sie ein Byte zurücksetzen müssen, z. B. beim Parsen in einigen Parsern, und Sie einen Rollback auf einen vorherigen Zustand durchführen müssen.

10. ReadRune: Liest ein einzelnes UTF-8-codiertes Unicode-Zeichen

// ReadRune 读取单个UTF-8编码的Unicode字符,并返回该字符及其字节大小。
// 如果编码的字符无效,它会消耗一个字节并返回unicode.ReplacementChar(U+FFFD)和大小为1。
func (b *Reader) ReadRune() (r rune, size int, err error) {
    
    
    // 循环直到缓冲区中有足够的数据以确保完整的rune被读取,
    // 或者达到缓冲区末尾,或者遇到错误。
    for b.r+utf8.UTFMax > b.w && !utf8.FullRune(b.buf[b.r:b.w]) && b.err == nil && b.w-b.r < len(b.buf) {
    
    
        b.fill() // b.w-b.r < len(buf) => buffer is not full
    }
    // 重置最近rune的大小。
    b.lastRuneSize = -1
    // 如果读取指针达到写指针,表示缓冲区为空,返回读取错误。
    if b.r == b.w {
    
    
        return 0, 0, b.readErr()
    }
    // 读取一个rune,并设置默认大小为1。
    r, size = rune(b.buf[b.r]), 1
    // 如果rune的值大于或等于utf8.RuneSelf,则表示可能占用多个字节,使用utf8.DecodeRune进行解码。
    if r >= utf8.RuneSelf {
    
    
        r, size = utf8.DecodeRune(b.buf[b.r:b.w])
    }
    // 更新读指针和记录最近读取的字节和rune的信息。
    b.r += size
    b.lastByte = int(b.buf[b.r-1])
    b.lastRuneSize = size
    return r, size, nil
}

erklären:

  • ReadRuneMethode ist Readereine Methode der Struktur, die zum Lesen eines einzelnen UTF-8-codierten Unicode-Zeichens verwendet wird.
  • Stellen Sie zunächst sicher, dass genügend Daten im Puffer vorhanden sind, indem Sie eine Schleife ausführen, um sicherzustellen, dass die gesamte Rune gelesen wird.
  • Wenn der Puffer leer ist, wird ein Lesefehler zurückgegeben.
  • Lies eine Rune und setze die Standardgröße auf 1.
  • Wenn der Wert von rune größer oder gleich ist utf8.RuneSelf, bedeutet dies, dass er mehrere Bytes belegen kann und utf8.DecodeRunedekodiert werden sollte.
  • Aktualisieren Sie den Lesezeiger und zeichnen Sie die zuletzt gelesenen Bytes und Runeninformationen auf.
  • Gibt die gelesene Rune, Größe und Null zurück, um anzuzeigen, dass kein Fehler vorliegt.

Wirkung:

  • ReadRuneDie Methode wird verwendet, um ein UTF-8-codiertes Unicode-Zeichen aus dem Puffer zu lesen.
  • Wenn nicht genügend Daten im Puffer vorhanden sind, um sicherzustellen, dass die vollständige Rune gelesen wird, fillwird eine Methode aufgerufen, um den Puffer zu füllen.
  • Die Methode behandelt auch mögliche Fehlerbedingungen, z. B. einen leeren Puffer oder ungültige codierte Zeichen.

11. UnreadRune: Macht die zuletzt gelesene Rune rückgängig

// UnreadRune 撤销最后读取的rune。如果最近在[Reader]上调用的方法不是[Reader.ReadRune],
// [Reader.UnreadRune]会返回错误(在这方面它比[Reader.UnreadByte]更严格,后者将从任何读取操作中撤销最后一个字节)。
func (b *Reader) UnreadRune() error {
    
    
    // 如果最近的rune的大小小于零或者读指针小于rune的大小,返回无效的rune撤销错误。
    if b.lastRuneSize < 0 || b.r < b.lastRuneSize {
    
    
        return ErrInvalidUnreadRune
    }
    // 撤销rune,更新读指针和记录最近读取的字节和rune的信息。
    b.r -= b.lastRuneSize
    b.lastByte = -1
    b.lastRuneSize = -1
    return nil
}

erklären:

  • UnreadRuneDie Methode ist Readereine Methode der Struktur und wird verwendet, um die zuletzt gelesene Rune rückgängig zu machen.
  • Überprüfen Sie zunächst, ob die Größe der neuesten Rune kleiner als Null ist oder ob der Lesezeiger kleiner als die Größe der Rune ist. Wenn ja, wird ein Fehler beim Rückgängigmachen einer ungültigen Rune zurückgegeben.
  • Brechen Sie dann die Rune ab, aktualisieren Sie den Lesezeiger und zeichnen Sie die zuletzt gelesenen Bytes und Runeninformationen auf.
  • Geben Sie Null zurück, um anzuzeigen, dass kein Fehler vorliegt.

Wirkung:

  • UnreadRuneMethode zum Rückgängigmachen der zuletzt gelesenen Rune, ohne den Lesestatus zu ändern.
  • Es prüft, ob die Bedingungen zum Rückgängigmachen erfüllt sind und gibt einen Fehler zurück, wenn die Bedingungen nicht erfüllt sind.
  • Der Rückgängig-Vorgang aktualisiert den Lesezeiger und zeichnet die zuletzt gelesenen Bytes und Runeninformationen auf.

12. ReadSlice: Liest das Slice bis zum Trennzeichen

// Buffered 返回当前缓冲区中可读取的字节数。
func (b *Reader) Buffered() int {
    
     return b.w - b.r }

// ReadSlice 读取直到输入中第一个定界符的位置,返回一个指向缓冲区中字节的切片。
// 这些字节在下一次读取时将不再有效。
// 如果 ReadSlice 在找到定界符之前遇到错误,
// 它将返回缓冲区中的所有数据和错误本身(通常是 io.EOF)。
// 如果缓冲区在没有定界符的情况下填满,ReadSlice 失败,返回错误 ErrBufferFull。
// 由于从 ReadSlice 返回的数据将被下一次 I/O 操作覆盖,
// 大多数客户端应该使用 [Reader.ReadBytes] 或 ReadString 来代替。
// 如果 line 不以定界符结束,ReadSlice 返回 err != nil。
func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
    
    
    s := 0 // 搜索开始索引
    for {
    
    
        // 在缓冲区中搜索定界符。
        if i := bytes.IndexByte(b.buf[b.r+s:b.w], delim); i >= 0 {
    
    
            i += s
            line = b.buf[b.r : b.r+i+1]
            b.r += i + 1
            break
        }

        // 有挂起的错误吗?
        if b.err != nil {
    
    
            line = b.buf[b.r:b.w]
            b.r = b.w
            err = b.readErr()
            break
        }

        // 缓冲区是否已满?
        if b.Buffered() >= len(b.buf) {
    
    
            b.r = b.w
            line = b.buf
            err = ErrBufferFull
            break
        }

        s = b.w - b.r // 不要重新扫描之前已经扫描过的区域

        b.fill() // 缓冲区未满时进行填充
    }

    // 处理最后一个字节(如果有的话)。
    if i := len(line) - 1; i >= 0 {
    
    
        b.lastByte = int(line[i])
        b.lastRuneSize = -1
    }

    return
}

erklären:

  • ReadSliceMethode ist Readereine Methode einer Struktur, die einen Slice aus dem Puffer bis zum angegebenen Trennzeichen liest.
  • Initialisieren Sie zunächst die Suche beginnend mit Index sNull.
  • Verwenden Sie eine Schleife, um den Puffer nach Trennzeichen zu durchsuchen.
    • Wenn das Trennzeichen gefunden wird, wird ein Slice erstellt, das lineauf die Bytes im Puffer zeigt, und der Lesezeiger wird aktualisiert b.r.
    • Bei einem anstehenden Fehler werden alle Daten im Puffer und der Fehler selbst zurückgegeben und der Lesezeiger aktualisiert.
    • Wenn der Puffer voll ist und kein Trennzeichen gefunden wird, werden der Puffer und der Fehler ErrBufferFull zurückgegeben.
    • Wenn keine der oben genannten Bedingungen erfüllt ist, füllen Sie den Puffer und setzen Sie die Suche fort.
  • Verarbeiten Sie das letzte Byte und aktualisieren Sie das letzte Byte der Datensatz- und Runeninformationen.
  • Gibt den gelesenen Slice und mögliche Fehler zurück.

Wirkung:

  • ReadSliceMethode zum Lesen von Slices aus dem Puffer bis zum angegebenen Trennzeichen.
  • Es bietet eine bequeme Möglichkeit, Daten zu verarbeiten, die Trennzeichen enthalten.
  • Beachten Sie, dass die meisten Clients stattdessen [Reader.ReadBytes] oder ReadString verwenden sollten, da die zurückgegebenen Daten durch den nächsten E/A-Vorgang überschrieben werden.

13. ReadLine: Eine Datenzeile lesen

Dieser Teil des Codes definiert ReadLineMethoden zum Lesen einer Datenzeile auf niedriger Ebene. Reader.ReadBytes('\n')Die meisten Anrufer sollten or Reader.ReadString('\n'), or verwenden Scanner.

// ReadLine 是一个低级别的读取一行数据的原语。大多数调用者应该使用
// [Reader.ReadBytes]('\n') 或 [Reader.ReadString]('\n'),或者使用 [Scanner]。
//
// ReadLine 试图返回一行数据,不包括行尾的字节。
// 如果行太长无法容纳在缓冲区中,则 isPrefix 被设置为 true,返回行的开头。
// 行的其余部分将在将来的调用中返回。当返回行的最后一部分时,isPrefix 将为 false。
// ReadLine 要么返回一个非空的行,要么返回一个错误,而不会同时返回两者。
//
// 从 ReadLine 返回的文本不包括行尾 ("\r\n" 或 "\n")。
// 如果输入在没有最终行尾的情况下结束,将不会给出指示或错误。
// 在调用 ReadLine 后调用 [Reader.UnreadByte] 将始终取消读取最后一个字节
// (可能是属于行尾的字符),即使该字节不是 ReadLine 返回的行的一部分。
func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error) {
    
    
    line, err = b.ReadSlice('\n')
    if err == ErrBufferFull {
    
    
        // 处理 "\r\n" 横跨缓冲区的情况。
        if len(line) > 0 && line[len(line)-1] == '\r' {
    
    
            // 将 '\r' 放回缓冲区并从 line 中删除。
            // 让下一次调用 ReadLine 检查 "\r\n"。
            if b.r == 0 {
    
    
                // 不应该达到的地方
                panic("bufio: tried to rewind past start of buffer")
            }
            b.r--
            line = line[:len(line)-1]
        }
        return line, true, nil
    }

    if len(line) == 0 {
    
    
        if err != nil {
    
    
            line = nil
        }
        return
    }
    err = nil

    if line[len(line)-1] == '\n' {
    
    
        drop := 1
        if len(line) > 1 && line[len(line)-2] == '\r' {
    
    
            drop = 2
        }
        line = line[:len(line)-drop]
    }
    return
}

erklären:

  • ReadLineDie Methode ist Readereine Methode der Struktur, die zum Lesen einer Datenzeile verwendet wird.
  • Rufen Sie zunächst ReadSlice('\n')die Methode auf, um eine Datenzeile zu lesen. Die zurückgegebene Methode lineenthält nicht das Ende der Zeile.
  • Wenn beim Lesen festgestellt wird, dass der Puffer voll ist und das Ende der Zeile den Puffer überschreitet, wird diese Situation speziell behandelt und \rzurück in den Puffer gelegt und linedaraus .
  • lineWird auf gesetzt , wenn die gelesene Zeilenlänge Null war und ein Fehler aufgetreten ist nil.
  • Wenn die Zeilendaten erfolgreich gelesen wurden und das letzte Zeichen der Zeile , ist \n, löschen Sie \nsie und evtl. davor \r.
  • Gibt die gelesenen Zeilendaten zurück line, ob es sich um das Präfix der Zeile handelt isPrefixund mögliche Fehler err.

Wirkung:

  • ReadLineDie Methode stellt eine Low-Level-Schnittstelle zum Lesen einer Datenzeile bereit.
  • ReadSliceDas Zeilenlesen wird durch implementiert und die Situation behandelt, in der das Zeilenende den Puffer kreuzt .
  • Die zurückgegebenen Bytes linemit Ausnahme des Zeilenendes isPrefixgeben an, ob noch Teile vorhanden sind, die nicht gelesen wurden, und errgeben an, ob ein Fehler aufgetreten ist.

14. CollectFragments: Fragmente sammeln

Dieser Teil des Codes definiert collectFragmentsMethoden, die die Eingabe lesen, bis das erste Trennzeichen auftritt delim. Es wird ein Ergebnistupel zurückgegeben: (Teil des vollen Puffers, verbleibende Bytes vor dem Trennzeichen, Gesamtbytes der ersten beiden Elemente, Fehler).

Das vollständige Ergebnis ist äquivalent zu bytes.Join(append(fullBuffers, finalFragment), nil), dessen Länge ist totalLen. Um dem Aufrufer die Minimierung von Zuordnungen und Kopien zu ermöglichen, werden die Ergebnisse auf diese Weise strukturiert.

func (b *Reader) collectFragments(delim byte) (fullBuffers [][]byte, finalFragment []byte, totalLen int, err error) {
    
    
    var frag []byte
    // 使用 ReadSlice 查找 delim,累积完整缓冲区。
    for {
    
    
        var e error
        frag, e = b.ReadSlice(delim)
        if e == nil {
    
     // 获取最后一个片段
            break
        }
        if e != ErrBufferFull {
    
     // 意外的错误
            err = e
            break
        }

        // 复制缓冲区。
        buf := bytes.Clone(frag)
        fullBuffers = append(fullBuffers, buf)
        totalLen += len(buf)
    }

    totalLen += len(frag)
    return fullBuffers, frag, totalLen, err
}

erklären:

  • collectFragmentsMethoden sind ReaderMethoden einer Struktur, die Daten aus der Eingabe lesen, bis das erste Trennzeichen auftritt delim.
  • Deklarieren Sie zunächst Variablen, fragum die jedes Mal gelesenen Fragmente zu speichern.
  • Verwenden Sie ReadSlicedie Methode, um das Trennzeichen zu durchlaufen delimund gleichzeitig den gesamten Puffer anzusammeln.
    • Wenn das Trennzeichen erfolgreich gefunden wird, bedeutet dies, dass das letzte Fragment erhalten und die Schleife durchbrochen wird.
    • Wenn der zurückgegebene Fehler nicht lautet ErrBufferFull, bedeutet dies, dass ein unerwarteter Fehler aufgetreten ist. Speichern Sie den Fehler errund verlassen Sie die Schleife.
    • Wenn der zurückgegebene Fehler lautet ErrBufferFull, was darauf hinweist, dass der Puffer voll ist, wird eine Kopie des Puffers zu hinzugefügt fullBuffersund die Gesamtzahl der Bytes wird akkumuliert.
  • Addieren Sie die Länge des letzten Fragments fragzur Gesamtzahl der Bytes.
  • Gibt einen Ausschnitt des vollen Puffers fullBuffers, das letzte Fragment frag, die Gesamtzahl der Bytes der ersten beiden Elemente totalLenund mögliche Fehler zurück err.

Wirkung:

  • collectFragmentsDie Methode bietet einen Mechanismus zum Aufbau eines vollständigen Puffers beim Lesen von Daten.
  • ReadSliceEs findet das Trennzeichen , indem es die Methode durchläuft delimund den gesamten Puffer akkumuliert, bis das Trennzeichen gefunden wird.
  • Die zurückgegebenen Ergebnisse ermöglichen es dem Aufrufer, die Speicherzuweisung und das Kopieren von Daten zu minimieren.

15. ReadBytes: Bytes lesen

Dieser Teil des Codes definiert ReadByteseine Methode, die die Eingabe bis zum ersten Auftreten des Trennzeichens liest delimund einen Slice zurückgibt, der die Daten und das Trennzeichen enthält. Wenn ein Fehler auftritt, bevor das Trennzeichen gefunden wird, werden die vor dem Fehler gelesenen Daten und der Fehler selbst (normalerweise io.EOF) zurückgegeben. ReadBytesWird nur zurückgegeben, wenn die zurückgegebenen Daten nicht mit einem Trennzeichen enden err != nil. Für einfache Zwecke kann es bequemer sein, den Scanner zu verwenden.

func (b *Reader) ReadBytes(delim byte) ([]byte, error) {
    
    
    // 使用 collectFragments 读取数据直到分隔符。
    full, frag, n, err := b.collectFragments(delim)
    
    // 为了容纳完整的片段和碎片,分配新的缓冲区。
    buf := make([]byte, n)
    n = 0
    
    // 将完整的片段和碎片复制到新的缓冲区中。
    for i := range full {
    
    
        n += copy(buf[n:], full[i])
    }
    copy(buf[n:], frag)
    
    return buf, err
}

erklären:

  • ReadBytesMethode ist Readereine Methode einer Struktur, die die Eingabe liest, bis das erste Trennzeichen auftritt delim.
  • Rufen Sie collectFragmentsdie Methode auf, um einen Ausschnitt des vollen Puffers full, das letzte Fragment frag, die Gesamtzahl der Bytes der ersten beiden Elemente nund mögliche Fehler abzurufen err.
  • Um das vollständige Fragment und das letzte Fragment unterzubringen, wird ein neuer Puffer bufmit der Länge zugewiesen n.
  • Verwenden Sie eine Schleife, um das vollständige Fragment und das letzte Fragment in einen neuen Puffer zu kopieren.
  • Gibt einen neuen Puffer zurück, der Daten, Trennzeichen und bufmögliche Fehler enthält err.

Wirkung:

  • ReadBytesDie Methode bietet eine Möglichkeit, Daten bis zu einem bestimmten Trennzeichen zu lesen und einen Slice einschließlich des Trennzeichens zurückzugeben.
  • collectFragmentsDer Prozess des Lesens von Daten aus der Eingabe wird durch den Aufruf der Methode implementiert.
  • Zur Vereinfachung der Verwendung werden das vollständige Fragment und das letzte Fragment in einem neuen Puffer zusammengeführt und zurückgegeben.

16. ReadString: String lesen

Dieser Teil des Codes definiert ReadStringeine Methode, die die Eingabe liest, bis das erste Trennzeichen auftritt, delimund eine Zeichenfolge zurückgibt, die die Daten und das Trennzeichen enthält. Wenn ein Fehler auftritt, bevor das Trennzeichen gefunden wird, werden die vor dem Fehler gelesenen Daten und der Fehler selbst (normalerweise io.EOF) zurückgegeben. ReadStringWird nur zurückgegeben, wenn die zurückgegebenen Daten nicht mit einem Trennzeichen enden err != nil. Für einfache Zwecke kann es bequemer sein, den Scanner zu verwenden.

func (b *Reader) ReadString(delim byte) (string, error) {
    
    
    // 使用 collectFragments 读取数据直到分隔符。
    full, frag, n, err := b.collectFragments(delim)
    
    // 为了容纳完整的片段和碎片,分配新的字符串构建器。
    var buf strings.Builder
    buf.Grow(n)
    
    // 将完整的片段和碎片写入字符串构建器。
    for _, fb := range full {
    
    
        buf.Write(fb)
    }
    buf.Write(frag)
    
    return buf.String(), err
}

erklären:

  • ReadStringMethode ist Readereine Methode einer Struktur, die die Eingabe liest, bis das erste Trennzeichen auftritt delim.
  • Rufen Sie collectFragmentsdie Methode auf, um einen Ausschnitt des vollen Puffers full, das letzte Fragment frag, die Gesamtzahl der Bytes der ersten beiden Elemente nund mögliche Fehler abzurufen err.
  • Um das vollständige Fragment und das letzte Fragment unterzubringen, wird ein neuer String-Builder zugewiesen buf, wobei ausreichend Speicherplatz vorab zugewiesen ist.
  • Verwenden Sie eine Schleife, um das vollständige Fragment und das letzte Fragment in den String Builder zu schreiben.
  • Gibt eine Zeichenfolge zurück, die Daten und Trennzeichen sowie mögliche Fehler enthält err.

Wirkung:

  • ReadStringDie Methode bietet eine Möglichkeit, Daten bis zu einem bestimmten Trennzeichen zu lesen und eine Zeichenfolge einschließlich des Trennzeichens zurückzugeben.
  • collectFragmentsDer Prozess des Lesens von Daten aus der Eingabe wird durch den Aufruf der Methode implementiert.
  • Zur Vereinfachung der Verwendung werden das vollständige Fragment und das letzte Fragment zu einem neuen String zusammengefasst und zurückgegeben.

Supongo que te gusta

Origin blog.csdn.net/weixin_49015143/article/details/135182305
Recomendado
Clasificación