Heading 2 Reader API class mt-12 Markdown The [Document API](#document-api) requires a `Reader` interface to iterate through lines in a document. A `Reader` has a `Read()` method that returns a string and an error. Each time it is called, it returns the next line from whichever source it is pulling them. Terrace for Go does not provide built-in readers, but you can easily create your own. Heading 3 Reader class mb-4 mt-12 Markdown An interface with a `Read()` method that returns the next line in a document and an error. The error should be `io.EOF` when the end of the document has been reached. CodeBlock go // Interface Definition type Reader interface { Read() (string, error) } Heading 3 StringReader class mb-4 mt-12 Markdown You can implement a `Reader` that reads from a string. CodeBlock go import ( "io" "strings" ) type StringReader struct { reader *strings.Reader } func (r *StringReader) Read() (string, error) { line, err := r.reader.ReadString('\n') if err != nil { return "", err } return strings.TrimRight(line, "\n"), nil } Markdown **Usage** CodeBlock go import ( "fmt" "io" "strings" "terrace.go" ) func main() { data := ` title Example Title line 2 ` reader := &StringReader{reader: strings.NewReader(data)} doc := terrace.NewTerraceDocument(reader, ' ') for { node, err := doc.Next() if err == io.EOF { break } if err != nil { panic(err) } fmt.Printf("%d %s\n", node.Level(), node.Content()) } } Heading 3 FileReader class mb-4 mt-12 Markdown You can use the `bufio` package to create a `Reader` for a file. CodeBlock go import ( "bufio" "os" ) type FileReader struct { scanner *bufio.Scanner } func NewFileReader(file *os.File) *FileReader { return &FileReader{scanner: bufio.NewScanner(file)} } func (r *FileReader) Read() (string, error) { if r.scanner.Scan() { return r.scanner.Text(), nil } if err := r.scanner.Err(); err != nil { return "", err } return "", io.EOF }