我试图在Go中编写一个扫描程序,以扫描连续行,并在返回之前清理掉行,以便您可以返回逻辑行。因此,给定以下SplitLine函数(Play):
func ScanLogicalLines(data []byte, atEOF bool) (int, []byte, error) { if atEOF && len(data) == 0 { return 0, nil, nil } i := bytes.IndexByte(data, '\n') for i > 0 && data[i-1] == '\\' { fmt.Printf("i: %d, data[i] = %q\n", i, data[i]) i = i + bytes.IndexByte(data[i+1:], '\n') } var match []byte = nil advance := 0 switch { case i >= 0: advance, match = i + 1, data[0:i] case atEOF: advance, match = len(data), data } token := bytes.Replace(match, []byte("\\\n"), []byte(""), -1) return advance, token, nil } func main() { simple := ` Just a test. See what is returned. \ when you have empty lines. Followed by a newline. ` scanner := bufio.NewScanner(strings.NewReader(simple)) scanner.Split(ScanLogicalLines) for scanner.Scan() { fmt.Printf("line: %q\n", scanner.Text()) } }
我希望代码返回类似以下内容:
line: "Just a test." line: "" line: "See what is returned, when you have empty lines." line: "" line: "Followed by a newline."
但是,它在返回第一行后停止。第二个电话返回1, "", nil。
1, "", nil
任何人有任何想法,还是一个错误?
我认为这是一个错误,因为即使返回的令牌为nil(bufio.SplitFunc),也不会将Advance value> 0用作进一步的读取调用:
如果数据尚未持有完整的令牌,例如,如果在扫描行时没有换行符,则SplitFunc可以返回(0,nil),以指示扫描程序将更多数据读入切片,并尝试以更长的切片开始于输入中的相同点。
bufio.Scanner默认的输入缓冲区为4096字节。这意味着它会一次读取最多此数量的内容,然后执行split功能。在您的情况下,扫描器可以一次读取所有输入,因为它远低于4096字节。 这意味着下一次读取将产生结果,EOF这是这里的主要问题。
bufio.Scanner
EOF
scanner.Scan
nil
"Just a test."
任何非null的令牌都将阻止这种情况。只要您返回非零令牌,扫描程序就不会检查EOF并继续执行令牌生成器。
您的代码返回nil令牌的原因是什么也没做就bytes.Replace返回 。。你可以阻止这种通过用容量返回片并没有元素,因为这将是非零:。nilappend([]byte(nil), nil...) == nil``make([]byte, 0, 1) != nil
bytes.Replace
append([]byte(nil), nil...) == nil``make([]byte, 0, 1) != nil