Skip to main content
Version: v2.2.82 (latest)
Reference · Core Type

Option

Represent optional values without nil pointers. Option is either Some(value) or None, providing type-safe handling of missing values.

01

Core API

Constructors

FunctionSignatureDescription
Somefunc Some[A any](value A) Option[A]Create an Option containing a value
Nonefunc None[A any]() Option[A]Create an empty Option
Offunc Of[A any](value A) Option[A]Alias for Some (monadic pure)
FromNillablefunc FromNillable[A any](ptr *A) Option[A]Convert pointer to Option (nil → None)
FromPredicatefunc FromPredicate[A any](pred func(A) bool) func(A) Option[A]Create Option based on predicate

Predicates

FunctionSignatureDescription
IsSomefunc IsSome[A any](opt Option[A]) boolCheck if Option contains a value
IsNonefunc IsNone[A any](opt Option[A]) boolCheck if Option is empty

Extractors

FunctionSignatureDescription
GetOrElsefunc GetOrElse[A any](defaultValue func() A) func(Option[A]) AExtract value or return default
ToNillablefunc ToNillable[A any](opt Option[A]) *AConvert to pointer (None → nil)
Matchfunc Match[A, B any](onNone func() B, onSome func(A) B) func(Option[A]) BPattern match on Option

Transformations

FunctionSignatureDescription
Mapfunc Map[A, B any](f func(A) B) func(Option[A]) Option[B]Transform the value if present
Chainfunc Chain[A, B any](f func(A) Option[B]) func(Option[A]) Option[B]FlatMap - chain optional operations
Apfunc Ap[A, B any](fa Option[A]) func(Option[func(A) B]) Option[B]Apply wrapped function to wrapped value
Flattenfunc Flatten[A any](opt Option[Option[A]]) Option[A]Flatten nested Options

Filtering

FunctionSignatureDescription
Filterfunc Filter[A any](pred func(A) bool) func(Option[A]) Option[A]Keep value only if predicate holds
FilterMapfunc FilterMap[A, B any](f func(A) Option[B]) func(Option[A]) Option[B]Map and filter in one operation

Combinators

FunctionSignatureDescription
Altfunc Alt[A any](second Option[A]) func(Option[A]) Option[A]Return first Some, or second if first is None
OrElsefunc OrElse[A any](alternative func() Option[A]) func(Option[A]) Option[A]Lazy alternative
02

Usage Examples

Basic Operations

basic.go
package main

import (
  "fmt"
  O "github.com/IBM/fp-go/v2/option"
)

func main() {
  // Create Options
  some := O.Some(42)
  none := O.None[int]()
  
  // Check for values
  fmt.Println(O.IsSome(some)) // true
  fmt.Println(O.IsNone(none)) // true
  
  // Extract values
  value := O.GetOrElse(func() int { return 0 })(some)
  fmt.Println(value) // 42
  
  defaultValue := O.GetOrElse(func() int { return 0 })(none)
  fmt.Println(defaultValue) // 0
}

Transformations

transformations.go
package main

import (
  "fmt"
  "strings"
  O "github.com/IBM/fp-go/v2/option"
  F "github.com/IBM/fp-go/v2/function"
)

func main() {
  // Map: transform the value
  opt := O.Some("hello")
  upper := F.Pipe1(
      opt,
      O.Map(strings.ToUpper),
  )
  fmt.Println(O.GetOrElse(func() string { return "" })(upper)) // HELLO
  
  // Chain: flatMap operations
  divide := func(a, b int) O.Option[int] {
      if b == 0 {
          return O.None[int]()
      }
      return O.Some(a / b)
  }
  
  result := F.Pipe1(
      O.Some(10),
      O.Chain(func(n int) O.Option[int] {
          return divide(n, 2)
      }),
  )
  fmt.Println(O.GetOrElse(func() int { return 0 })(result)) // 5
  
  // Filter: keep value only if predicate holds
  filtered := F.Pipe1(
      O.Some(42),
      O.Filter(func(n int) bool { return n > 50 }),
  )
  fmt.Println(O.IsNone(filtered)) // true (42 is not > 50)
}

Pattern Matching

pattern_matching.go
package main

import (
  "fmt"
  O "github.com/IBM/fp-go/v2/option"
)

func main() {
  opt := O.Some(42)
  
  // Match: handle both cases
  result := O.Match(
      func() string { return "No value" },
      func(n int) string { return fmt.Sprintf("Value: %d", n) },
  )(opt)
  
  fmt.Println(result) // Value: 42
}

Practical Example: Configuration

config.go
package main

import (
  "fmt"
  O "github.com/IBM/fp-go/v2/option"
  F "github.com/IBM/fp-go/v2/function"
)

type Config struct {
  Port    O.Option[int]
  Host    O.Option[string]
  Timeout O.Option[int]
}

func getPort(config Config) int {
  return F.Pipe1(
      config.Port,
      O.GetOrElse(func() int { return 8080 }),
  )
}

func getHost(config Config) string {
  return F.Pipe1(
      config.Host,
      O.GetOrElse(func() string { return "localhost" }),
  )
}

func main() {
  // Config with explicit values
  config1 := Config{
      Port: O.Some(3000),
      Host: O.Some("0.0.0.0"),
      Timeout: O.Some(30),
  }
  fmt.Printf("Server: %s:%d
", getHost(config1), getPort(config1))
  // Server: 0.0.0.0:3000
  
  // Config with defaults
  config2 := Config{
      Port: O.None[int](),
      Host: O.None[string](),
      Timeout: O.Some(60),
  }
  fmt.Printf("Server: %s:%d
", getHost(config2), getPort(config2))
  // Server: localhost:8080
}

Working with Pointers

pointers.go
package main

import (
  "fmt"
  O "github.com/IBM/fp-go/v2/option"
)

func findUser(id string) *User {
  if id == "123" {
      return &User{ID: "123", Name: "Alice"}
  }
  return nil
}

type User struct {
  ID   string
  Name string
}

func main() {
  // Convert pointer to Option
  userPtr := findUser("123")
  opt := O.FromNillable(userPtr)
  
  fmt.Println(O.IsSome(opt)) // true
  
  // Convert back to pointer
  ptr := O.ToNillable(opt)
  if ptr != nil {
      fmt.Println(ptr.Name) // Alice
  }
  
  // Handle missing user
  missingPtr := findUser("999")
  missingOpt := O.FromNillable(missingPtr)
  fmt.Println(O.IsNone(missingOpt)) // true
}
03

Why Use Option?

Steps
  • Type Safety — Compiler ensures you handle both Some and None cases

    required
  • No Nil Panics — Eliminates nil pointer dereference errors

    required
  • Explicit Intent — Makes it clear when a value might be absent

    recommended
  • Composability — Works seamlessly with pipe, map, chain, and other fp-go functions

    recommended
  • Functional Style — Encourages declarative, expression-based code

    optional
Before
traditional.go
// ❌ Traditional nil handling
func getUser(id string) *User {
  // Might return nil
  return db.FindUser(id)
}

user := getUser("123")
if user != nil {
  // Easy to forget nil check
  fmt.Println(user.Name) // Potential panic!
}
After
option_based.go
// ✅ Option-based handling
func getUser(id string) O.Option[User] {
  user := db.FindUser(id)
  return O.FromNillable(user)
}

// Compiler forces you to handle both cases
O.Match(
  func() { fmt.Println("User not found") },
  func(u User) { fmt.Println(u.Name) },
)(getUser("123"))