Golang script: Difference between revisions
From wikinotes
(Created page with "A collection of shellscript inspired utility functions,<br> with stream-like asynchronous piping. Very clever. = Documentation = <blockquote> {| class="wikitable" |- | github || https://github.com/bitfield/script |- |} </blockquote><!-- Documentation -->") |
|||
(2 intermediate revisions by the same user not shown) | |||
Line 10: | Line 10: | ||
|} | |} | ||
</blockquote><!-- Documentation --> | </blockquote><!-- Documentation --> | ||
= Example = | |||
<blockquote> | |||
<syntaxhighlight lang="go"> | |||
import "script" | |||
script.Exec("ping 127.0.0.1").Stdout() | |||
</syntaxhighlight> | |||
</blockquote><!-- Usage --> | |||
= How it Works = | |||
<blockquote> | |||
It implements railroad-style programming pipes asynchronously/interchangeably between functions/subprocesses.<br> | |||
This is done using a Reader/Writer representing STDIN/STDOUT.<br> | |||
Similar to unix pipes, | |||
* when the Reader is closed, the pipes stop processing information | |||
* when any of the Filter() methods returns err, the pipes following it stop processing information | |||
Here's an oversimplification of the flow: | |||
<syntaxhighlight lang="go"> | |||
type Pipe struct { | |||
Reader ReadAutoCloser | |||
stdout io.Writer | |||
Err error | |||
} | |||
fun NewPipe() *Pipe {...} | |||
// https://github.com/bitfield/script/blob/master/script.go#L473 | |||
func (p *Pipe) Filter(filter func(io.Reader, io.Writer) error) *Pipe { | |||
if p.Err() != nil { | |||
return p | |||
} | |||
pr, pw := io.Pipe() | |||
filter(p.Reader, pw) | |||
} | |||
</syntaxhighlight> | |||
<syntaxhighlight lang="go"> | |||
pipe := NewPipe() | |||
pipe\ | |||
.Filter( | |||
func (r io.Reader, w io.Writer) error { | |||
w.Write(...) // write result | |||
return err := errors.New("some error") // flag an error | |||
} | |||
)\ | |||
.Filter(func (r io.Reader, w io.Writer) error { ... })\ | |||
.Filter(func (r io.Reader, w io.Writer) error { ... })\ | |||
.Filter(func (r io.Reader, w io.Writer) error { ... }) | |||
.Stdout() | |||
</syntaxhighlight> | |||
</blockquote><!-- How it Works --> |
Latest revision as of 04:07, 15 December 2022
A collection of shellscript inspired utility functions,
with stream-like asynchronous piping. Very clever.
Documentation
github https://github.com/bitfield/script
Example
import "script" script.Exec("ping 127.0.0.1").Stdout()
How it Works
It implements railroad-style programming pipes asynchronously/interchangeably between functions/subprocesses.
This is done using a Reader/Writer representing STDIN/STDOUT.
Similar to unix pipes,
- when the Reader is closed, the pipes stop processing information
- when any of the Filter() methods returns err, the pipes following it stop processing information
Here's an oversimplification of the flow:
type Pipe struct { Reader ReadAutoCloser stdout io.Writer Err error } fun NewPipe() *Pipe {...} // https://github.com/bitfield/script/blob/master/script.go#L473 func (p *Pipe) Filter(filter func(io.Reader, io.Writer) error) *Pipe { if p.Err() != nil { return p } pr, pw := io.Pipe() filter(p.Reader, pw) }pipe := NewPipe() pipe\ .Filter( func (r io.Reader, w io.Writer) error { w.Write(...) // write result return err := errors.New("some error") // flag an error } )\ .Filter(func (r io.Reader, w io.Writer) error { ... })\ .Filter(func (r io.Reader, w io.Writer) error { ... })\ .Filter(func (r io.Reader, w io.Writer) error { ... }) .Stdout()