Skip to main content
Version: v2.2.82 (latest)
Getting started · Section 03 / 03

5-minute quickstart.

Install fp-go, write your first program, and learn the core composition patterns — Pipe, Map, Chain, GetOrElse — in one sitting.

// You'll learn
5patterns
Pipe, Map, Chain, GetOrElse, automatic error propagation.
// Prereqs
Go 1.24+ and basic Go familiarity.
// You'll build
A safe divider and a composable calculator.
01

Prerequisites

Before you start.
  • Go 1.24+ for v2 (recommended)
  • Go 1.18+ for v1 (legacy)
  • Basic understanding of Go
02

Install fp-go.

Choose your version. v2 is recommended for any new project.

shelltested
# Initialize your Go module (if not already done)
go mod init myapp

# Install fp-go v2
go get github.com/IBM/fp-go/v2
Why v2.
  • Latest features (Result, Effect, idiomatic packages)
  • Better type inference
  • Actively maintained
  • Requires Go 1.24+
03

Your first program.

A safe divider. Compare the three approaches side-by-side.

main.gotested
package main

import (
  "errors"
  "fmt"
  "github.com/IBM/fp-go/v2/function"
  "github.com/IBM/fp-go/v2/result"
)

// Pure function that returns Result instead of (value, error)
func divide(a, b int) result.Result[int] {
  if b == 0 {
      return result.Err[int](errors.New("division by zero"))
  }
  return result.Ok(a / b)
}

func main() {
  // Compose operations with automatic error handling
  finalResult := function.Pipe2(
      divide(10, 2),
      result.Map(func(x int) int { return x * 2 }),
      result.GetOrElse(func() int { return 0 }),
  )

  fmt.Println("Result:", finalResult) // Output: Result: 10

  // Error case is handled automatically
  errorResult := function.Pipe2(
      divide(10, 0), // Returns Err
      result.Map(func(x int) int { return x * 2 }), // Skipped!
      result.GetOrElse(func() int { return 0 }), // Returns default
  )

  fmt.Println("Error result:", errorResult) // Output: Error result: 0
}
Benefits.

No repetitive error checking. Easy composition. Errors propagate automatically. Business logic stays prominent.

Run it

shell
go run main.go
output
Result: 10
Error result: 0
04

Understanding the pattern.

Four building blocks: Result/Either return types, Pipe to compose, Map to transform, GetOrElse to extract.

1. Pure functions return results

signature.go
// Instead of this:
func divide(a, b int) (int, error)

// We write this:
func divide(a, b int) result.Result[int]

2. Compose with Pipe

pipe.go
result := function.Pipe2(
  operation1(),      // Returns Result[A]
  operation2,        // A -> Result[B]
  operation3,        // B -> C
)

Pipe feeds the output of one function into the next, automatically handling errors.

3. Transform with Map

map.go
result.Map(func(x int) int {
  return x * 2
})

Map transforms the value inside a Result/Either — but only if it's successful. Errors pass through unchanged.

4. Extract with GetOrElse

getorelse.go
result.GetOrElse(func() int {
  return 0
})

GetOrElse extracts the value or provides a default if there was an error.

05

A more complex example.

Chain multiple operations into one pipeline. Failure in any step short-circuits the rest.

calculator.gotested
package main

import (
  "errors"
  "fmt"
  "github.com/IBM/fp-go/v2/function"
  "github.com/IBM/fp-go/v2/result"
)

func divide(a, b int) result.Result[int] {
  if b == 0 {
      return result.Err[int](errors.New("division by zero"))
  }
  return result.Ok(a / b)
}

func sqrt(n int) result.Result[int] {
  if n < 0 {
      return result.Err[int](errors.New("cannot sqrt negative number"))
  }
  // Simplified integer sqrt
  result := 0
  for result*result <= n {
      result++
  }
  return result.Ok(result - 1)
}

func calculate(a, b, c int) result.Result[string] {
  return function.Pipe3(
      divide(a, b),                                    // 100 / 4 = 25
      result.Chain(func(x int) result.Result[int] {   // Chain another Result operation
          return divide(x, c)                          // 25 / 5 = 5
      }),
      result.Chain(sqrt),                              // sqrt(5) ≈ 2
      result.Map(func(x int) string {                  // Convert to string
          return fmt.Sprintf("Final result: %d", x)
      }),
  )
}

func main() {
  // Success case
  success := calculate(100, 4, 5)
  fmt.Println(result.GetOrElse(func() string {
      return "Error occurred"
  })(success))
  // Output: Final result: 2

  // Error case (division by zero)
  failure := calculate(100, 0, 5)
  fmt.Println(result.GetOrElse(func() string {
      return "Error occurred"
  })(failure))
  // Output: Error occurred
}
ConceptWhen to useNotes
Chaina.k.a. FlatMap
Use when your transformation returns another Result/Either.
MapFunctor map
Use when your transformation returns a plain value.
Pipefunction.PipeN
Compose multiple operations into a pipeline.
Auto errorShort-circuit
If any step fails, subsequent steps are skipped.
06

What's next?

Pick a thread to keep learning.

TopicPageWhy
WhyWhy fp-go?
Understand the benefits and when to reach for it.
Pure functionsPure functions
The foundation of functional programming.
MonadsMonads
The pattern behind Result, Either, IO, etc.
ResultResult
Recommended type for v2 error handling.
EitherEither
Generic sum type.
OptionOption
Handle optional values safely.
IOIO
Manage side effects.
Recipes · errorsError handling
Production-style patterns.
Recipes · HTTPHTTP requests
Effectful pipelines.

Common questions

When should I use fp-go?

Good fit: complex error handling, data transformation pipelines, composable business logic, testing-heavy codebases.

Not ideal: simple CRUD, performance-critical hot paths (use idiomatic packages), teams unfamiliar with FP.

Is fp-go production-ready?

Yes. fp-go is used in production at IBM and elsewhere. v2 is actively maintained and recommended for new projects.

What's the performance impact?

Standard packages: minimal overhead. Idiomatic packages (v2): 2–32× faster, near-native performance. See the performance guide for details.

Migrating from v1 to v2?

See the migration guide for a complete walkthrough of the 5 breaking changes and how to handle them.

07

Summary

What you learned6 / 6 complete
  • How to install fp-go (v1 or v2)
  • How to write pure functions with Result/Either
  • How to compose operations with Pipe
  • How to transform values with Map and Chain
  • How to handle errors automatically
  • How to build complex pipelines
Next step.

Read Why fp-go? to understand when and why to use functional programming in Go.

Need help?