trustmaster/goflow

Flow-based and dataflow programming library for Go (golang)

Go

1,674

279 commits

updated Jun 5, 2026

See the code

README

GoFlow

Go Reference Go Version CI codecov

Dataflow and Flow-based programming library for Go.

GoFlow is a lean and opinionated implementation of Flow-based programming (FBP) that lets you design applications as graphs of components reacting to data as it flows through the graph.

Flow-based programming is a programming paradigm that defines applications as networks of black-box processes that exchange data across predefined connections by message passing, where the connections are specified externally to the processes.

Features

  • Concurrent — graph nodes run in parallel via goroutines and channels.
  • Structural — applications are described as components, their ports, and the connections between them.
  • Reactive — system behavior is defined by how components react to events or manage their lifecycle.
  • Asynchronous by default — events have no predetermined order unless you enforce one.
  • Isolated — communication replaces shared state; components don't share memory.

Installation

GoFlow requires Go 1.23 or later.

go get github.com/trustmaster/goflow

Then import it in your code:

import "github.com/trustmaster/goflow"

Quick Start

Below is a complete program that builds a simple two-component network: one greets names, the other prints the result.

Greeter example diagram

package main

import (
	"fmt"

	"github.com/trustmaster/goflow"
)

// Greeter sends greetings.
type Greeter struct {
	Name <-chan string // input port
	Res  chan<- string // output port
}

// Process reads incoming names and sends back greetings.
func (c *Greeter) Process() {
	for name := range c.Name {
		c.Res <- fmt.Sprintf("Hello, %s!", name)
	}
}

// Printer prints its input on screen.
type Printer struct {
	Line <-chan string // input port
}

// Process reads lines and prints them.
func (c *Printer) Process() {
	for line := range c.Line {
		fmt.Println(line)
	}
}

// NewGreetingApp defines the application graph.
func NewGreetingApp() *goflow.Graph {
	n := goflow.NewGraph()
	n.Add("greeter", new(Greeter))
	n.Add("printer", new(Printer))
	n.Connect("greeter", "Res", "printer", "Line")
	n.MapInPort("In", "greeter", "Name")
	return n
}

func main() {
	net := NewGreetingApp()
	in := make(chan string)
	net.SetInPort("In", in)

	wait := goflow.Run(net)

	in <- "John"
	in <- "Boris"
	in <- "Hanna"
	close(in)

	<-wait
}

Why the wait channel? The flow-based world is asynchronous — events don't necessarily happen in the order they were sent. The wait channel signals when the network has fully completed, preventing premature program termination.

Terminology

TermDescription
ComponentThe basic processing element. Its structure consists of input/output ports and state fields; its behavior is defined by event handlers. Analogous to a Class.
ConnectionA link between two ports in the graph. In GoFlow this is a typed channel.
GraphA higher-level entity composed of components and connections. Can represent composite components or entire applications. Analogous to a Class.
NetworkA running instance of a Graph. Analogous to an Object.
PortA property through which a Component or Graph communicates with the outside world (input/output). In GoFlow this is a channel field.
ProcessA running instance of a Component. Analogous to an Object.

More terms can be found in the Flowbased.org Terminology and the FBP wiki.

DSL / FBP Syntax

GoFlow includes a built-in dsl package that lets you define application graphs using standard Flow-Based Programming (FBP) syntax in .fbp files instead of writing Go code.

import "github.com/trustmaster/goflow/dsl"

A minimal .fbp file looks like this:

# Declare the sender's input as a graph port
INPORT=Sender.IN:IN
# Declare the receiver's output as a graph port
OUTPORT=Receiver.OUT:OUT

# Declare two processes and connect them
Sender(test/sender) OUT -> IN Receiver(test/receiver)

Load and run it with:

g, err := dsl.LoadFile("graph.fbp", factory)

The dsl package supports process declarations, connections, array ports, IIPs (initial information packets), and port exports. See the dsl package README for the full syntax guide and API reference.

Documentation

Wiki

  • Components — ports, events, process, and state.
  • Graphs — structure definition and behavior.

GoDoc

go doc github.com/trustmaster/goflow

Or view the online reference.

Roadmap

  • Integration with NoFlo-UI / Flowhub (in progress)
  • Distributed networks via TCP/IP and UDP
  • Reflection and monitoring of networks

Contributing

Contributions are welcome! Please open an issue or pull request on GitHub.

Before submitting changes, make sure your code passes the linter and tests:

make test

License

MIT

data-flow
dataflow
fbp
go
goflow

trustmaster/goflow

Flow-based and dataflow programming library for Go (golang)

Go

1,674

279 commits

updated Jun 5, 2026

See the code

README

GoFlow

Go Reference Go Version CI codecov

Dataflow and Flow-based programming library for Go.

GoFlow is a lean and opinionated implementation of Flow-based programming (FBP) that lets you design applications as graphs of components reacting to data as it flows through the graph.

Flow-based programming is a programming paradigm that defines applications as networks of black-box processes that exchange data across predefined connections by message passing, where the connections are specified externally to the processes.

Features

  • Concurrent — graph nodes run in parallel via goroutines and channels.
  • Structural — applications are described as components, their ports, and the connections between them.
  • Reactive — system behavior is defined by how components react to events or manage their lifecycle.
  • Asynchronous by default — events have no predetermined order unless you enforce one.
  • Isolated — communication replaces shared state; components don't share memory.

Installation

GoFlow requires Go 1.23 or later.

go get github.com/trustmaster/goflow

Then import it in your code:

import "github.com/trustmaster/goflow"

Quick Start

Below is a complete program that builds a simple two-component network: one greets names, the other prints the result.

Greeter example diagram

package main

import (
	"fmt"

	"github.com/trustmaster/goflow"
)

// Greeter sends greetings.
type Greeter struct {
	Name <-chan string // input port
	Res  chan<- string // output port
}

// Process reads incoming names and sends back greetings.
func (c *Greeter) Process() {
	for name := range c.Name {
		c.Res <- fmt.Sprintf("Hello, %s!", name)
	}
}

// Printer prints its input on screen.
type Printer struct {
	Line <-chan string // input port
}

// Process reads lines and prints them.
func (c *Printer) Process() {
	for line := range c.Line {
		fmt.Println(line)
	}
}

// NewGreetingApp defines the application graph.
func NewGreetingApp() *goflow.Graph {
	n := goflow.NewGraph()
	n.Add("greeter", new(Greeter))
	n.Add("printer", new(Printer))
	n.Connect("greeter", "Res", "printer", "Line")
	n.MapInPort("In", "greeter", "Name")
	return n
}

func main() {
	net := NewGreetingApp()
	in := make(chan string)
	net.SetInPort("In", in)

	wait := goflow.Run(net)

	in <- "John"
	in <- "Boris"
	in <- "Hanna"
	close(in)

	<-wait
}

Why the wait channel? The flow-based world is asynchronous — events don't necessarily happen in the order they were sent. The wait channel signals when the network has fully completed, preventing premature program termination.

Terminology

TermDescription
ComponentThe basic processing element. Its structure consists of input/output ports and state fields; its behavior is defined by event handlers. Analogous to a Class.
ConnectionA link between two ports in the graph. In GoFlow this is a typed channel.
GraphA higher-level entity composed of components and connections. Can represent composite components or entire applications. Analogous to a Class.
NetworkA running instance of a Graph. Analogous to an Object.
PortA property through which a Component or Graph communicates with the outside world (input/output). In GoFlow this is a channel field.
ProcessA running instance of a Component. Analogous to an Object.

More terms can be found in the Flowbased.org Terminology and the FBP wiki.

DSL / FBP Syntax

GoFlow includes a built-in dsl package that lets you define application graphs using standard Flow-Based Programming (FBP) syntax in .fbp files instead of writing Go code.

import "github.com/trustmaster/goflow/dsl"

A minimal .fbp file looks like this:

# Declare the sender's input as a graph port
INPORT=Sender.IN:IN
# Declare the receiver's output as a graph port
OUTPORT=Receiver.OUT:OUT

# Declare two processes and connect them
Sender(test/sender) OUT -> IN Receiver(test/receiver)

Load and run it with:

g, err := dsl.LoadFile("graph.fbp", factory)

The dsl package supports process declarations, connections, array ports, IIPs (initial information packets), and port exports. See the dsl package README for the full syntax guide and API reference.

Documentation

Wiki

  • Components — ports, events, process, and state.
  • Graphs — structure definition and behavior.

GoDoc

go doc github.com/trustmaster/goflow

Or view the online reference.

Roadmap

  • Integration with NoFlo-UI / Flowhub (in progress)
  • Distributed networks via TCP/IP and UDP
  • Reflection and monitoring of networks

Contributing

Contributions are welcome! Please open an issue or pull request on GitHub.

Before submitting changes, make sure your code passes the linter and tests:

make test

License

MIT

data-flow
dataflow
fbp
go
goflow

Project health

Overall

2.8/10

Maintained

0/10

Code review

0/10
OpenSSF Scorecard

Significant stargazers

Clayton Coleman

1,510 followers · starred Sep 2014

Henri Bergius

806 followers · starred Feb 2012

Mickaël Rémond

244 followers · starred Dec 2015

Stéphane Campinas

35 followers · starred Feb 2015