Documentation ¶
Overview ¶
Package script aims to make it easy to write shell-type scripts in Go, for general system administration purposes: reading files, counting lines, matching strings, and so on.
Index ¶
- type Pipe
- func (p *Pipe) AppendFile(fileName string) (int64, error)
- func (p *Pipe) Basename() *Pipe
- func (p *Pipe) Bytes() ([]byte, error)
- func (p *Pipe) Close() error
- func (p *Pipe) Column(col int) *Pipe
- func (p *Pipe) Concat() *Pipe
- func (p *Pipe) CountLines() (int, error)
- func (p *Pipe) Dirname() *Pipe
- func (p *Pipe) EachLine(process func(string, *strings.Builder)) *Pipedeprecated
- func (p *Pipe) Echo(s string) *Pipe
- func (p *Pipe) Error() error
- func (p *Pipe) Exec(command string) *Pipe
- func (p *Pipe) ExecForEach(command string) *Pipe
- func (p *Pipe) ExitStatus() int
- func (p *Pipe) Filter(filter func(io.Reader, io.Writer) error) *Pipe
- func (p *Pipe) FilterLine(filter func(string) string) *Pipe
- func (p *Pipe) FilterScan(filter func(string, io.Writer)) *Pipe
- func (p *Pipe) First(n int) *Pipe
- func (p *Pipe) Freq() *Pipe
- func (p *Pipe) JQ(query string) *Pipe
- func (p *Pipe) Join() *Pipe
- func (p *Pipe) Last(n int) *Pipe
- func (p *Pipe) Match(s string) *Pipe
- func (p *Pipe) MatchRegexp(re *regexp.Regexp) *Pipe
- func (p *Pipe) Read(b []byte) (int, error)
- func (p *Pipe) Reject(s string) *Pipe
- func (p *Pipe) RejectRegexp(re *regexp.Regexp) *Pipe
- func (p *Pipe) Replace(search, replace string) *Pipe
- func (p *Pipe) ReplaceRegexp(re *regexp.Regexp, replace string) *Pipe
- func (p *Pipe) SHA256Sum() (string, error)
- func (p *Pipe) SHA256Sums() *Pipe
- func (p *Pipe) SetError(err error)
- func (p *Pipe) Slice() ([]string, error)
- func (p *Pipe) Stdout() (int, error)
- func (p *Pipe) String() (string, error)
- func (p *Pipe) Wait()
- func (p *Pipe) WithError(err error) *Pipe
- func (p *Pipe) WithReader(r io.Reader) *Pipe
- func (p *Pipe) WithStdout(w io.Writer) *Pipe
- func (p *Pipe) WriteFile(fileName string) (int64, error)
- type ReadAutoCloser
Examples ¶
- Args
- Echo
- Exec (Exit_status_not_zero)
- Exec (Exit_status_zero)
- Exec (Ok)
- File
- FindFiles
- IfExists (False)
- IfExists (True)
- ListFiles
- Pipe.Basename
- Pipe.Bytes
- Pipe.Column
- Pipe.Concat
- Pipe.CountLines
- Pipe.Dirname
- Pipe.EachLine
- Pipe.Echo
- Pipe.Exec
- Pipe.ExecForEach
- Pipe.ExitStatus
- Pipe.Filter
- Pipe.FilterLine (Stdlib)
- Pipe.FilterLine (User)
- Pipe.FilterScan
- Pipe.First
- Pipe.Freq
- Pipe.JQ
- Pipe.Join
- Pipe.Last
- Pipe.Match
- Pipe.MatchRegexp
- Pipe.Read
- Pipe.Reject
- Pipe.RejectRegexp
- Pipe.Replace
- Pipe.ReplaceRegexp
- Pipe.SHA256Sum
- Pipe.SHA256Sums
- Pipe.Slice
- Pipe.Stdout
- Pipe.String
- Slice
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Pipe ¶
type Pipe struct { Reader ReadAutoCloser // contains filtered or unexported fields }
Pipe represents a pipe object with an associated ReadAutoCloser.
func Args ¶ added in v0.7.0
func Args() *Pipe
Args creates a pipe containing the program's command-line arguments, one per line.
Example ¶
package main import ( "github.com/bitfield/script" ) func main() { script.Args().Stdout() // prints command-line arguments }
Output:
func Echo ¶ added in v0.3.0
Echo creates a pipe containing the supplied string.
Example ¶
package main import ( "github.com/bitfield/script" ) func main() { script.Echo("Hello, world!").Stdout() }
Output: Hello, world!
func Exec ¶ added in v0.5.0
Exec runs an external command and creates a pipe containing its combined output (stdout and stderr).
If the command had a non-zero exit status, the pipe's error status will also be set to the string "exit status X", where X is the integer exit status.
For convenience, you can get this value directly as an integer by calling ExitStatus on the pipe.
Even in the event of a non-zero exit status, the command's output will still be available in the pipe. This is often helpful for debugging. However, because String is a no-op if the pipe's error status is set, if you want output you will need to reset the error status before calling String.
Note that Exec can also be used as a filter, in which case the given command will read from the pipe as its standard input.
Example (Exit_status_not_zero) ¶
package main import ( "fmt" "github.com/bitfield/script" ) func main() { p := script.Exec("false") p.Wait() fmt.Println(p.ExitStatus()) }
Output: 1
Example (Exit_status_zero) ¶
package main import ( "fmt" "github.com/bitfield/script" ) func main() { p := script.Exec("echo") p.Wait() fmt.Println(p.ExitStatus()) }
Output: 0
Example (Ok) ¶
package main import ( "github.com/bitfield/script" ) func main() { script.Exec("echo Hello, world!").Stdout() }
Output: Hello, world!
func File ¶
File creates a pipe that reads from the file at the specified path.
Example ¶
package main import ( "github.com/bitfield/script" ) func main() { script.File("testdata/hello.txt").Stdout() }
Output: hello world
func FindFiles ¶ added in v0.16.0
FindFiles takes a directory path and creates a pipe listing all the files in the directory and its subdirectories recursively, one per line, like Unix `find -type f`. If the path doesn't exist or can't be read, the pipe's error status will be set.
Each line of the output consists of a slash-separated pathname, starting with the initial directory. For example, if the starting directory is "test", and it contains 1.txt and 2.txt:
test/1.txt test/2.txt
Example ¶
package main import ( "github.com/bitfield/script" ) func main() { script.FindFiles("testdata/multiple_files_with_subdirectory").Stdout() }
Output: testdata/multiple_files_with_subdirectory/1.txt testdata/multiple_files_with_subdirectory/2.txt testdata/multiple_files_with_subdirectory/3.tar.zip testdata/multiple_files_with_subdirectory/dir/.hidden testdata/multiple_files_with_subdirectory/dir/1.txt testdata/multiple_files_with_subdirectory/dir/2.txt
func IfExists ¶ added in v0.14.0
IfExists tests whether the specified file exists, and creates a pipe whose error status reflects the result. If the file doesn't exist, the pipe's error status will be set, and if the file does exist, the pipe will have no error status. This can be used to do some operation only if a given file exists:
IfExists("/foo/bar").Exec("/usr/bin/something")
Example (False) ¶
package main import ( "github.com/bitfield/script" ) func main() { script.IfExists("doesntexist").Echo("found it").Stdout() }
Output:
Example (True) ¶
package main import ( "github.com/bitfield/script" ) func main() { script.IfExists("./testdata/hello.txt").Echo("found it").Stdout() }
Output: found it
func ListFiles ¶ added in v0.11.0
ListFiles creates a pipe containing the files and directories matching the supplied path, one per line. The path can be the name of a directory (`/path/to/dir`), the name of a file (`/path/to/file`), or a glob (wildcard expression) conforming to the syntax accepted by filepath.Match (for example `/path/to/*`).
ListFiles does not recurse into subdirectories (use FindFiles for this).
Example ¶
package main import ( "github.com/bitfield/script" ) func main() { script.ListFiles("testdata/multiple_files_with_subdirectory").Stdout() }
Output: testdata/multiple_files_with_subdirectory/1.txt testdata/multiple_files_with_subdirectory/2.txt testdata/multiple_files_with_subdirectory/3.tar.zip testdata/multiple_files_with_subdirectory/dir
func Slice ¶ added in v0.11.0
Slice creates a pipe containing each element of the supplied slice of strings, one per line.
Example ¶
package main import ( "github.com/bitfield/script" ) func main() { input := []string{"1", "2", "3"} script.Slice(input).Stdout() }
Output: 1 2 3
func (*Pipe) AppendFile ¶ added in v0.4.0
AppendFile appends the contents of the pipe to the specified file, and returns the number of bytes successfully written, or an error. If the file does not exist, it is created.
func (*Pipe) Basename ¶ added in v0.14.0
Basename reads a list of filepaths from the pipe, one per line, and removes any leading directory components from each line. So, for example, `/usr/local/bin/foo` would become just `foo`. This is the complementary operation to Dirname.
If a line is empty, Basename will produce '.'. Trailing slashes are removed. The behaviour of Basename is the same as filepath.Base (not by coincidence).
Example ¶
package main import ( "github.com/bitfield/script" ) func main() { input := []string{ "", "/", "/root", "/tmp/example.php", "/var/tmp/", "./src/filters", "C:/Program Files", } script.Slice(input).Basename().Stdout() }
Output: . / root example.php tmp filters Program Files
func (*Pipe) Bytes ¶ added in v0.8.0
Bytes returns the contents of the pipe as a []]byte, or an error.
Example ¶
package main import ( "fmt" "github.com/bitfield/script" ) func main() { data, err := script.Echo("hello").Bytes() if err != nil { panic(err) } fmt.Println(data) }
Output: [104 101 108 108 111]
func (*Pipe) Close ¶
Close closes the pipe's associated reader. This is a no-op if the reader is not also a Closer.
func (*Pipe) Column ¶ added in v0.9.0
Column produces only the Nth column of each line of input, where '1' is the first column, and columns are delimited by whitespace. Specifically, whatever Unicode defines as whitespace ('WSpace=yes').
Lines containing less than N columns will be dropped altogether.
Example ¶
package main import ( "github.com/bitfield/script" ) func main() { input := []string{ "PID TT STAT TIME COMMAND", " 1 ?? Ss 873:17.62 /sbin/launchd", " 50 ?? Ss 13:18.13 /usr/libexec/UserEventAgent (System)", " 51 ?? Ss 22:56.75 /usr/sbin/syslogd", } script.Slice(input).Column(1).Stdout() }
Output: PID 1 50 51
func (*Pipe) Concat ¶ added in v0.8.0
Concat reads a list of file paths from the pipe, one per line, and produces the contents of all those files in sequence. If there are any errors (for example, non-existent files), these will be ignored, execution will continue, and the pipe's error status will not be set.
This makes it convenient to write programs that take a list of input files on the command line. For example:
script.Args().Concat().Stdout()
The list of files could also come from a file:
script.File("filelist.txt").Concat()
...or from the output of a command:
script.Exec("ls /var/app/config/").Concat().Stdout()
Each input file will be closed once it has been fully read. If any of the files can't be opened or read, `Concat` will simply skip these and carry on, without setting the pipe's error status. This mimics the behaviour of Unix `cat`.
Example ¶
package main import ( "github.com/bitfield/script" ) func main() { input := []string{ "testdata/test.txt", "testdata/doesntexist.txt", "testdata/hello.txt", } script.Slice(input).Concat().Stdout() }
Output: This is the first line in the file. Hello, world. This is another line in the file. hello world
func (*Pipe) CountLines ¶
CountLines returns the number of lines of input, or an error.
Example ¶
package main import ( "fmt" "github.com/bitfield/script" ) func main() { n, err := script.Echo("a\nb\nc\n").CountLines() if err != nil { panic(err) } fmt.Println(n) }
Output: 3
func (*Pipe) Dirname ¶ added in v0.14.0
Dirname reads a list of pathnames from the pipe, one per line, and produces only the parent directories of each pathname. For example, `/usr/local/bin/foo` would become just `/usr/local/bin`. This is the complementary operation to Basename.
If a line is empty, Dirname will produce a '.'. Trailing slashes are removed, unless Dirname returns the root folder. Otherwise, the behaviour of Dirname is the same as filepath.Dir (not by coincidence).
Example ¶
package main import ( "github.com/bitfield/script" ) func main() { input := []string{ "", "/", "/root", "/tmp/example.php", "/var/tmp/", "./src/filters", "C:/Program Files", } script.Slice(input).Dirname().Stdout() }
Output: . / / /tmp /var ./src C:
func (*Pipe) EachLine
deprecated
added in
v0.3.0
EachLine calls the specified function for each line of input, passing it the line as a string, and a *strings.Builder to write its output to.
Deprecated: use FilterLine or FilterScan instead, which run concurrently and don't do unnecessary reads on the input.
Example ¶
package main import ( "strings" "github.com/bitfield/script" ) func main() { script.File("testdata/test.txt").EachLine(func(line string, out *strings.Builder) { out.WriteString("> " + line + "\n") }).Stdout() }
Output: > This is the first line in the file. > Hello, world. > This is another line in the file.
func (*Pipe) Echo ¶ added in v0.2.0
Echo produces the supplied string.
Example ¶
package main import ( "github.com/bitfield/script" ) func main() { script.NewPipe().Echo("Hello, world!").Stdout() }
Output: Hello, world!
func (*Pipe) Exec ¶ added in v0.5.0
Exec runs an external command, sending it the contents of the pipe as input, and produces the command's combined output (`stdout` and `stderr`). The effect of this is to filter the contents of the pipe through the external command.
If the command had a non-zero exit status, the pipe's error status will also be set to the string "exit status X", where X is the integer exit status.
Example ¶
package main import ( "github.com/bitfield/script" ) func main() { script.Echo("Hello, world!").Exec("tr a-z A-Z").Stdout() }
Output: HELLO, WORLD!
func (*Pipe) ExecForEach ¶ added in v0.15.0
ExecForEach runs the supplied command once for each line of input, and produces its combined output. The command string is interpreted as a Go template, so `{{.}}` will be replaced with the input value, for example.
If any command resulted in a non-zero exit status, the pipe's error status will also be set to the string "exit status X", where X is the integer exit status.
Example ¶
package main import ( "github.com/bitfield/script" ) func main() { script.Echo("a\nb\nc\n").ExecForEach("echo {{.}}").Stdout() }
Output: a b c
func (*Pipe) ExitStatus ¶ added in v0.5.0
ExitStatus returns the integer exit status of a previous command, if the pipe's error status is set, and if the error matches the pattern "exit status %d". Otherwise, it returns zero.
Example ¶
package main import ( "fmt" "github.com/bitfield/script" ) func main() { p := script.Exec("echo") fmt.Println(p.ExitStatus()) }
Output: 0
func (*Pipe) Filter ¶ added in v0.19.0
Filter filters the contents of the pipe through the supplied function, which takes an io.Reader (the filter input) and an io.Writer (the filter output), and returns an error, which will be set on the pipe.
The filter function runs concurrently, so its goroutine will not complete until the pipe has been fully read. If you just need to make sure all concurrent filters have completed, call Wait on the end of the pipe.
Example ¶
package main import ( "fmt" "io" "github.com/bitfield/script" ) func main() { script.Echo("hello world").Filter(func(r io.Reader, w io.Writer) error { n, err := io.Copy(w, r) fmt.Fprintf(w, "\nfiltered %d bytes\n", n) return err }).Stdout() }
Output: hello world filtered 11 bytes
func (*Pipe) FilterLine ¶ added in v0.19.0
FilterLine filters the contents of the pipe, a line at a time, through the supplied function, which takes the line as a string and returns a string (the filter output). The filter function runs concurrently.
Example (Stdlib) ¶
package main import ( "strings" "github.com/bitfield/script" ) func main() { script.Echo("a\nb\nc").FilterLine(strings.ToUpper).Stdout() }
Output: A B C
Example (User) ¶
package main import ( "github.com/bitfield/script" ) func main() { script.Echo("a\nb\nc").FilterLine(func(line string) string { return "> " + line }).Stdout() }
Output: > a > b > c
func (*Pipe) FilterScan ¶ added in v0.19.0
FilterScan filters the contents of the pipe, a line at a time, through the supplied function, which takes the line as a string and an io.Writer (the filtero output). The filter function runs concurrently.
Example ¶
package main import ( "fmt" "io" "github.com/bitfield/script" ) func main() { script.Echo("a\nb\nc").FilterScan(func(line string, w io.Writer) { fmt.Fprintf(w, "scanned line: %q\n", line) }).Stdout() }
Output: scanned line: "a" scanned line: "b" scanned line: "c"
func (*Pipe) First ¶ added in v0.9.0
First produces only the first N lines of input, or the whole input if there are less than N lines. If N is zero or negative, there is no output at all.
Example ¶
package main import ( "github.com/bitfield/script" ) func main() { script.Echo("a\nb\nc\n").First(2).Stdout() }
Output: a b
func (*Pipe) Freq ¶ added in v0.9.0
Freq produces only unique lines from the input, prefixed with a frequency count, in descending numerical order (most frequent lines first). Lines with equal frequency will be sorted alphabetically.
This is a common pattern in shell scripts to find the most frequently-occurring lines in a file:
sort testdata/freq.input.txt |uniq -c |sort -rn
Freq's behaviour is like the combination of Unix `sort`, `uniq -c`, and `sort -rn` used here. You can use Freq in combination with First to get, for example, the ten most common lines in a file:
script.Stdin().Freq().First(10).Stdout()
Like `uniq -c`, Freq left-pads its count values if necessary to make them easier to read:
10 apple
4 banana 2 orange 1 kumquat
Example ¶
package main import ( "strings" "github.com/bitfield/script" ) func main() { input := strings.Join([]string{ "apple", "orange", "banana", "banana", "apple", "orange", "kumquat", "apple", "orange", "apple", "banana", "banana", "apple", "apple", "orange", "apple", "apple", "apple", "apple", }, "\n") script.Echo(input).Freq().Stdout() }
Output: 10 apple 4 banana 4 orange 1 kumquat
func (*Pipe) JQ ¶ added in v0.20.0
JQ takes a query in the 'jq' language and applies it to the input (presumed to be JSON), producing the result. An invalid query will set the appropriate error on the pipe.
The exact dialect of JQ supported is that provided by github.com/itchyny/gojq, whose documentation explains the differences between it and 'standard' JQ.
Example ¶
package main import ( "fmt" "github.com/bitfield/script" ) func main() { kernel := "Darwin" arch := "x86_64" query := fmt.Sprintf(".assets[] | select(.name | endswith(\"%s_%s.tar.gz\")).browser_download_url", kernel, arch) script.File("testdata/releases.json").JQ(query).Stdout() }
Output: "https://github.com/mbarley333/blackjack/releases/download/v0.3.3/blackjack_0.3.3_Darwin_x86_64.tar.gz"
func (*Pipe) Join ¶ added in v0.7.0
Join produces its input as a single space-separated string, which will always end with a newline.
Example ¶
package main import ( "github.com/bitfield/script" ) func main() { script.Echo("hello\nworld\n").Join().Stdout() }
Output: hello world
func (*Pipe) Last ¶ added in v0.12.0
Last produces only the last N lines of input, or the whole input if there are less than N lines. If N is zero or negative, there is no output at all.
Example ¶
package main import ( "github.com/bitfield/script" ) func main() { script.Echo("a\nb\nc\n").Last(2).Stdout() }
Output: b c
func (*Pipe) Match ¶ added in v0.2.0
Match produces only lines that contain the specified string.
Example ¶
package main import ( "github.com/bitfield/script" ) func main() { script.Echo("a\nb\nc\n").Match("b").Stdout() }
Output: b
func (*Pipe) MatchRegexp ¶ added in v0.3.0
MatchRegexp produces only lines that match the specified compiled regular expression.
Example ¶
package main import ( "regexp" "github.com/bitfield/script" ) func main() { re := regexp.MustCompile("w.*d") script.Echo("hello\nworld\n").MatchRegexp(re).Stdout() }
Output: world
func (*Pipe) Read ¶ added in v0.8.1
Read reads up to len(b) bytes from the data source into b. It returns the number of bytes read and any error encountered. At end of file, or on a nil pipe, Read returns 0, io.EOF.
Unlike most sinks, Read does not necessarily read the whole contents of the pipe. It will read as many bytes as it takes to fill the slice.
Example ¶
package main import ( "fmt" "github.com/bitfield/script" ) func main() { buf := make([]byte, 12) n, err := script.Echo("hello world\n").Read(buf) if err != nil { panic(err) } fmt.Println(n) }
Output: 12
func (*Pipe) Reject ¶ added in v0.2.0
Reject produces only lines that do not contain the specified string.
Example ¶
package main import ( "github.com/bitfield/script" ) func main() { script.Echo("a\nb\nc\n").Reject("b").Stdout() }
Output: a c
func (*Pipe) RejectRegexp ¶ added in v0.3.0
RejectRegexp produces only lines that don't match the specified compiled regular expression.
Example ¶
package main import ( "regexp" "github.com/bitfield/script" ) func main() { re := regexp.MustCompile("w.*d") script.Echo("hello\nworld\n").RejectRegexp(re).Stdout() }
Output: hello
func (*Pipe) Replace ¶ added in v0.10.0
Replace replaces all occurrences of the 'search' string with the 'replace' string.
Example ¶
package main import ( "github.com/bitfield/script" ) func main() { script.Echo("a\nb\nc\n").Replace("b", "replacement").Stdout() }
Output: a replacement c
func (*Pipe) ReplaceRegexp ¶ added in v0.10.0
ReplaceRegexp replaces all matches of the specified compiled regular expression with the 'replace' string. '$' characters in the replace string are interpreted as in regexp.Expand; for example, "$1" represents the text of the first submatch.
Example ¶
package main import ( "regexp" "github.com/bitfield/script" ) func main() { re := regexp.MustCompile("w.*d") script.Echo("hello\nworld\n").ReplaceRegexp(re, "replacement").Stdout() }
Output: hello replacement
func (*Pipe) SHA256Sum ¶ added in v0.17.0
SHA256Sum returns the hex-encoded SHA-256 hash of its input, or an error.
Example ¶
package main import ( "fmt" "github.com/bitfield/script" ) func main() { sum, err := script.Echo("hello world").SHA256Sum() if err != nil { panic(err) } fmt.Println(sum) }
Output: b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
func (*Pipe) SHA256Sums ¶ added in v0.17.0
SHA256Sums reads a list of file paths from the pipe, one per line, and produces the hex-encoded SHA-256 hash of each file. Any files that cannot be opened or read will be ignored.
Example ¶
package main import ( "github.com/bitfield/script" ) func main() { script.Echo("testdata/test.txt").SHA256Sums().Stdout() }
Output: a562c9c95e2ff3403e7ffcd8508c6b54d47d5f251387758d3e63dbaaa8296341
func (*Pipe) Slice ¶ added in v0.18.0
Slice returns the input as a slice of strings, one element per line, or an error.
An empty pipe will produce an empty slice. A pipe containing a single empty line (that is, a single `\n` character) will produce a slice containing the empty string.
Example ¶
package main import ( "fmt" "github.com/bitfield/script" ) func main() { s, err := script.Echo("a\nb\nc\n").Slice() if err != nil { panic(err) } fmt.Println(s) }
Output: [a b c]
func (*Pipe) Stdout ¶ added in v0.6.0
Stdout writes the input to the pipe's configured standard output, and returns the number of bytes successfully written, or an error.
Example ¶
package main import ( "fmt" "github.com/bitfield/script" ) func main() { n, err := script.Echo("a\nb\nc\n").Stdout() if err != nil { panic(err) } fmt.Println(n) }
Output: a b c 6
func (*Pipe) String ¶
String returns the input as a string, or an error.
Example ¶
package main import ( "fmt" "github.com/bitfield/script" ) func main() { s, err := script.Echo("hello\nworld").String() if err != nil { panic(err) } fmt.Println(s) }
Output: hello world
func (*Pipe) Wait ¶ added in v0.19.0
func (p *Pipe) Wait()
Wait reads the input to completion and discards it. This is mostly useful for waiting until all concurrent filter stages have finished.
func (*Pipe) WithError ¶
WithError sets the specified error on the pipe and returns the modified pipe.
func (*Pipe) WithReader ¶
WithReader sets the pipe's input to the specified reader. If necessary, the reader will be automatically closed once it has been completely read.
func (*Pipe) WithStdout ¶ added in v0.18.2
WithStdout sets the pipe's standard output to the specified reader, instead of the default os.Stdout.
type ReadAutoCloser ¶ added in v0.8.0
type ReadAutoCloser struct {
// contains filtered or unexported fields
}
ReadAutoCloser represents a pipe source that will be automatically closed once it has been fully read.
func NewReadAutoCloser ¶ added in v0.8.0
func NewReadAutoCloser(r io.Reader) ReadAutoCloser
NewReadAutoCloser returns an ReadAutoCloser wrapping the supplied Reader. If the Reader is not a Closer, it will be wrapped in a NopCloser to make it closable.
func (ReadAutoCloser) Close ¶ added in v0.8.0
func (a ReadAutoCloser) Close() error
Close closes the data source associated with a, and returns the result of that close operation.
func (ReadAutoCloser) Read ¶ added in v0.8.0
func (a ReadAutoCloser) Read(buf []byte) (n int, err error)
Read reads up to len(buf) bytes from the data source into buf. It returns the number of bytes read and any error encountered. At end of file, Read returns 0, io.EOF. In the EOF case, the data source will be closed.