go-streaming is a Go stream processing package inspired by conduit that:
- Makes reusable/composable streams that can be connected together like building blocks
- Supports generics for extra type safety
- Supports cancellation via context
- Handles errors anywhere in a stream and does a clean shutdown
- Is pull-based which guarantees constant memory use
go get github.com/chrismwendt/go-streaming
Create a source:
- streaming.SourceReadertakes an- io.Readersuch as- os.Stdinand turns it into a stream of- []bytechunks
- streaming.SourceSliceemits each element of a slice- []Tdownstream one by one
- streaming.SourceExecstreams stdout from a command
Then streaming.Connect the source to other streams:
- streaming.Taketakes N values from upstream and passes them downstream, then stops
- streaming.FuncToStreamtakes a function- func(A) Band makes a stream that calls it on each element
Then streaming.Connect that stream to a sink:
- streaming.SinkWritertakes an- io.Writersuch as- os.Stdoutand writes- []bytechunks to it
- streaming.SinkSliceaccumulates all upstream values into a slice- []T
- streaming.SinkExecstreams into the stdin of a command
Finally run the stream with streaming.Run(ctx, stream). That will also return the result of the stream, if relevant (e.g. streaming.SinkSlice returns []T).
s1 := streaming.SourceReader(os.Stdin)
s2 := streaming.Connect(s1, streaming.SinkWriter(os.Stdout))
result := streaming.Run(context.Background(), s2)
if result.Error != nil {
  panic(result.Error)
}s1 := streaming.SourceReader(os.Stdin)
s2 := streaming.Connect(s1, streaming.SplitOn("\n"))
s3 := streaming.Connect(s2, streaming.Take(5))
s4 := streaming.Connect(s3, streaming.SinkWriter(os.Stdout))
result := streaming.Run(context.Background(), s4)
if result.Error != nil {
  panic(result.Error)
}s1 := streaming.SourceReader(os.Stdin)
s2 := streaming.Connect(s1, streaming.Concat[byte]())
s3 := streaming.Connect(s2, streaming.SplitOn(byte('\n')))
length := func(ctx context.Context, stream streaming.Stream[streaming.Void, byte, streaming.Unit]) streaming.Result[int] {
  return streaming.Run(ctx, streaming.Connect(stream, streaming.Count[byte]()))
}
s4 := streaming.Connect(s3, streaming.FuncToStreamCtx(length))
s5 := streaming.Connect(s4, streaming.Max())
result := streaming.Run(context.Background(), s5)
if result.Error != nil {
  panic(result.Error)
}
maybeSum := *result.Value
if maybeSum == nil {
  fmt.Println("input contains no lines")
}
sum := *maybeSum
fmt.Println("Max line length:", sum)- github.com/reugn/go-streams doesn't support generics or cancellation, but has built-in parallelism