使用扫描仪时如何获取包括换行符在内的行长?

I'm using Scan to scan lines 1 at a time from an IMAP connection, which are supposed to end with , but I suspect some of the lines I'm getting are actually ending in just , because I'm getting an incorrect amount of data when parsing the body atom in a particular instance

(* 8620 FETCH (BODY[] {7060} is what I'm getting for the body in just this one email, but that seems to be longer than the count if count newlines as 2 bytes)

// ...
r := bufio.NewScanner(d.conn)
for r.Scan() {
    line := r.Text()
    len(line) // gets the line length WITHOUT the newline
}

Would there be any way to get the length with the newline? Or get the length of the token that the scanner stopped with?

While this is an answer answers my question in the literal sense about including the and potential , using the Scanner in in the first place while reading an IMAP server's responses is NOT the correct tool, and I will be rewriting my use of the Scanner and replacing it with bufio.Reader.


You can specify custom split functions for use in your Scanner, so for example, you can port the ScanLines split function to one that doesn't drop the newline characters with the token that gets returned.

// ...
r := bufio.NewScanner(d.conn)
r.Split(func(data []byte, atEOF bool) (advance int, token []byte, err error) {
    if atEOF && len(data) == 0 {
        return 0, nil, nil
    }
    if i := bytes.IndexByte(data, '
'); i >= 0 {
        // We have a full newline-terminated line.
        return i + 1, data[0 : i+1], nil
    }
    // If we're at EOF, we have a final, non-terminated line. Return it.
    if atEOF {
        return len(data), data, nil
    }
    // Request more data.
    return 0, nil, nil
})

for r.Scan() {
    line := r.Text()
    len(line) // now gets the line length WITH the newline
}

The default SplitFunc provided to bufio.NewScanner is SplitLines which includes a call to dropCR which, per the comments, matches on end-of-line ?. Because the Scanner will optionally find and drop carriage returns, you won't be able to find the full length of a line using the bufio.Scanner.

From my experience, it's common to use the Scanner when things are basic, as it's a convenience struct. Otherwise bufio.Reader provides more flexibility. bufio.Reader#ReadBytes(delim byte) will give you what you're looking for.