// read reads blocks of 4096 bytes from the File, sending lines to the // channel as it encounters newlines. If EOF is encountered, the partial line // is returned to be concatenated with on the next call. func (t *Tailer) read(f afero.File, partialIn string) (partialOut string, err error) { partial := partialIn b := make([]byte, 0, 4096) for { n, err := f.Read(b[:cap(b)]) b = b[:n] if err != nil { return partial, err } for i, width := 0, 0; i < len(b) && i < n; i += width { var rune rune rune, width = utf8.DecodeRune(b[i:]) switch { case rune != '\n': partial += string(rune) default: // send off line for processing t.lines <- partial // reset accumulator partial = "" } } } }