Peeking content

In the previous example, we fixed a number of bytes in order to store the content at every read before printing it. Some functionality is offered by the bufio package that makes it possible to use an underlying buffer that is not directly controlled by the user, and makes it possible to execute a very important operation named peek.

Peeking is the ability to read content without advancing the reader cursor. Here, under the hood, the peeked data is stored in the buffer. Each reading operation checks whether there's data in this buffer and if there is any, that data is returned while removing it from the buffer. This works like a queue (first in, first out).

The possibilities that this simple operation opens are endless, and they all derive from peeking until the desired sequence of data is found, and then the interested chunk is actually read. The most common uses of this operation include the following:

  • The buffers keeps reading from the reader until it finds a newline character (read one line at time).
  • The same operation is used until a space is found (read one word at a time).

The structure that allows an application to achieve this behavior is bufio.Scanner. This makes it possible to define what the splitting function is and has the following type:

type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)

This function stops when an error is returned, otherwise it returns the number of bytes to advance in the content, and eventually a token. The implemented functions in the package are as follows:

  • ScanBytes: Byte tokens 
  • ScanRunes: Runes tokens
  • ScanWordWords tokens 
  • ScanLinesLine tokens 

We could implement a file reader that counts the number of lines with just a reader. The resulting program will try to emulate what the Unix wc -l command does.

An example of printing a file and counting lines is shown in the following code:

func main() {
if len(os.Args) != 2 {
fmt.Println("Please specify a path.")
return
}
f, err := os.Open(os.Args[1])
if err != nil {
fmt.Println("Error:", err)
return
}
defer f.Close()
r := bufio.NewReader(f) // wrapping the reader with a buffered one
var rowCount int
for err == nil {
var b []byte
for moar := true; err == nil && moar; {
b, moar, err = r.ReadLine()
if err == nil {
fmt.Print(string(b))
}
}
// each time moar is false, a line is completely read
if err == nil {
fmt.Println()
rowCount++

}
}
if err != nil && err != io.EOF {
fmt.Println(" Error:", err)
return
}
fmt.Println(" Row count:", rowCount)
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.23.147