fn

package module
v0.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 6, 2026 License: MIT Imports: 4 Imported by: 0

README

Documentation

Overview

Package fn uses a gloo-foo command as an ordinary Go data function.

A gloo command is a github.com/gloo-foo/framework.Command[[]byte, []byte]: a transform over a stream of input lines. That shape is ideal for wiring pipelines and Unix executables, but awkward to call from ordinary code, where you have a buffer or a reader and want a buffer or a reader back. This package closes that gap: it adapts any command — one command, or several composed — into a Pipeline whose method values are plain, directly-callable functions over standard data types.

pipeline := fn.Chain(grep, sort, uniq) // fn.Pipeline
run := pipeline.String                 // func(string) (string, error)
out, err := run("my input")            // call it like any function

Three data shapes are offered, all from the same command:

Output framing matches a shell filter: each result line is written followed by '\n', so fn.Of(cat).String("abc") yields "abc\n" — identical to printf 'abc' | cat. Pipeline.Lines returns the lines without terminators.

A Pipeline is an immutable value: safe to copy, reuse, and share.

Example (NormalFunction)

A composed pipeline is called like an ordinary function over string data.

package main

import (
	"bytes"
	"fmt"

	gloo "github.com/gloo-foo/framework"
	"github.com/gloo-foo/framework/patterns"

	"github.com/gloo-foo/fn"
)

// upper is a stand-in command; a real program passes a cmd-* command (Cat, Grep,
// Sort, …) or any Command[[]byte, []byte].
func upper() gloo.Command[[]byte, []byte] {
	return patterns.Map(func(line []byte) ([]byte, error) {
		return bytes.ToUpper(line), nil
	})
}

func keepNonEmpty() gloo.Command[[]byte, []byte] {
	return patterns.Filter(func(line []byte) (bool, error) {
		return len(line) > 0, nil
	})
}

func main() {
	pipeline := fn.Chain(upper(), keepNonEmpty())

	out, err := pipeline.String("hello\n\nworld")
	if err != nil {
		panic(err)
	}
	fmt.Printf("%q\n", out)
}
Output:
"HELLO\nWORLD\n"

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Pipeline

type Pipeline struct {
	// contains filtered or unexported fields
}

Pipeline is a gloo command — one command or several composed — in ordinary data-function form. Its method values (Pipeline.Bytes, Pipeline.String, Pipeline.Lines, Pipeline.Reader) are plain, directly-callable functions over standard byte and reader data.

It is an immutable value with value-receiver methods: safe to copy, reuse across calls, and share across goroutines. Each call runs the command over its own fresh input, so one Pipeline serves many invocations.

func Chain

func Chain(cmds ...gloo.Command[[]byte, []byte]) Pipeline

Chain composes commands left to right into a single Pipeline, feeding each command's output stream to the next. With no arguments it is the identity pipeline (input passes through unchanged).

func Of

func Of(cmd gloo.Command[[]byte, []byte]) Pipeline

Of adapts a single command into a Pipeline.

func (Pipeline) Bytes

func (p Pipeline) Bytes(input []byte) ([]byte, error)

Bytes runs the pipeline over input and returns the whole output, each result line terminated by '\n' — matching a shell filter. It uses context.Background; see Pipeline.BytesContext to pass a context.

Example

Bytes runs a command over a whole buffer.

package main

import (
	"bytes"
	"fmt"

	gloo "github.com/gloo-foo/framework"
	"github.com/gloo-foo/framework/patterns"

	"github.com/gloo-foo/fn"
)

// upper is a stand-in command; a real program passes a cmd-* command (Cat, Grep,
// Sort, …) or any Command[[]byte, []byte].
func upper() gloo.Command[[]byte, []byte] {
	return patterns.Map(func(line []byte) ([]byte, error) {
		return bytes.ToUpper(line), nil
	})
}

func main() {
	out, _ := fn.Of(upper()).Bytes([]byte("abc"))
	fmt.Printf("%q\n", out)
}
Output:
"ABC\n"

func (Pipeline) BytesContext

func (p Pipeline) BytesContext(ctx context.Context, input []byte) ([]byte, error)

BytesContext is Pipeline.Bytes with an explicit context: cancelling ctx stops the pipeline.

func (Pipeline) Lines

func (p Pipeline) Lines(input []byte) ([]string, error)

Lines runs the pipeline over input and returns the output as lines, each without its terminator. It uses context.Background; see Pipeline.LinesContext to pass a context.

func (Pipeline) LinesContext

func (p Pipeline) LinesContext(ctx context.Context, input []byte) ([]string, error)

LinesContext is Pipeline.Lines with an explicit context: cancelling ctx stops the pipeline.

func (Pipeline) Reader

func (p Pipeline) Reader(input io.Reader) io.ReadCloser

Reader runs the pipeline over input and returns its output as a lazy reader: output is produced only as the returned reader is read, so unbounded input (yes | head) never buffers. Each result line is emitted followed by '\n'. Any error the pipeline raises surfaces from Read. Close abandons an unfinished read, tearing the pipeline down; reading to io.EOF releases it too — the caller MUST do one or the other, or the producing goroutine blocks forever (the io.Pipe contract). It uses context.Background; see Pipeline.ReaderContext to pass a context.

Example

Reader streams output lazily from a reader, so unbounded input never buffers.

package main

import (
	"bytes"
	"fmt"
	"io"
	"strings"

	gloo "github.com/gloo-foo/framework"
	"github.com/gloo-foo/framework/patterns"

	"github.com/gloo-foo/fn"
)

// upper is a stand-in command; a real program passes a cmd-* command (Cat, Grep,
// Sort, …) or any Command[[]byte, []byte].
func upper() gloo.Command[[]byte, []byte] {
	return patterns.Map(func(line []byte) ([]byte, error) {
		return bytes.ToUpper(line), nil
	})
}

func main() {
	r := fn.Of(upper()).Reader(strings.NewReader("one\ntwo"))
	out, _ := io.ReadAll(r)
	fmt.Printf("%q\n", out)
}
Output:
"ONE\nTWO\n"

func (Pipeline) ReaderContext

func (p Pipeline) ReaderContext(ctx context.Context, input io.Reader) io.ReadCloser

ReaderContext is Pipeline.Reader with an explicit context: cancelling ctx stops the pipeline and the next Read reports the cancellation.

The command runs in a goroutine that pumps its output through an io.Pipe; the returned reader is the pipe's read half. Because io.Pipe is synchronous, the command only advances as the reader consumes it — the source of the laziness and backpressure.

func (Pipeline) String

func (p Pipeline) String(input string) (string, error)

String is Pipeline.Bytes over string data: it runs the pipeline over input and returns the whole output as a string. It uses context.Background; see Pipeline.StringContext to pass a context.

func (Pipeline) StringContext

func (p Pipeline) StringContext(ctx context.Context, input string) (string, error)

StringContext is Pipeline.String with an explicit context: cancelling ctx stops the pipeline.

func (Pipeline) To

func (p Pipeline) To(next gloo.Command[[]byte, []byte]) Pipeline

To returns a new Pipeline with next appended as the final stage. The receiver is unchanged.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL