"tail -f"-Like Generator in Go: An Idiomatic Approach with io.Reader
In the programming realm, the need to follow the evolving contents of a file often arises. Python offers a convenient function tailored to this task, akin to UNIX's "tail -f." However, implementing a similar capability in Go requires a different approach due to language nuances.
In Go, the code provided in the question employs a goroutine to monitor the file and yield new lines as they become available. While functional, it may raise concerns about resource usage and idiomatic Go programming practices.
An alternative solution involves creating a wrapper around an io.Reader that exhibits "tail-like" behavior. This approach offers a number of advantages:
The implementation of the "tailReader" itself is straightforward:
<code class="go">type tailReader struct { io.ReadCloser } func (t tailReader) Read(b []byte) (int, error) { for { n, err := t.ReadCloser.Read(b) if n > 0 { return n, nil } else if err != io.EOF { return n, err } time.Sleep(10 * time.Millisecond) } }</code>
An optional helper function can be used to instantiate the "tailReader":
<code class="go">func newTailReader(fileName string) (tailReader, error) { f, err := os.Open(fileName) if err != nil { return tailReader{}, err } if _, err := f.Seek(0, 2); err != nil { return tailReader{}, err } return tailReader{f}, nil }</code>
To utilize the "tailReader," simply wrap it around a bufio.Scanner or other reader-based IO mechanism:
<code class="go">t, err := newTailReader("somefile") if err != nil { log.Fatal(err) } defer t.Close() scanner := bufio.NewScanner(t) for scanner.Scan() { fmt.Println(scanner.Text()) } if err := scanner.Err(); err != nil { fmt.Fprintln(os.Stderr, "reading:", err) }</code>
In summary, the "tailReader" approach leverages the strengths of Go's reader interface to provide an idiomatic and efficient solution for following the contents of a file. It offers simplicity, resource efficiency, and seamless integration with existing Go code.
The above is the detailed content of How to Implement a \'tail -f\'-Like Generator in Go: An Idiomatic Approach with io.Reader?. For more information, please follow other related articles on the PHP Chinese website!