mo for Go: Complete Guide with Examples

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Library mo for Go: Monads and Functional Patterns

\n\n

Welcome to the world of functional programming in Go! The mo library (from monads) is a powerful tool that brings monad concepts and functional patterns, popular in Haskell, Scala, and Rust, to the imperative Go language. If you have ever struggled with error handling via if err != nil, endless nested nil checks, or cumbersome call chains, mo offers an elegant solution.

\n\n

The main goal of the library is to provide type-safe containers (Option, Result, Either) that encapsulate possible states (presence/absence of a value, success/error) and allow you to work with them in a functional style. Instead of writing dozens of conditional statements, you build transformation chains where each step is handled automatically. This makes the code more readable, predictable, and less error-prone, especially in complex business logic.

\n\n

The mo library does not try to turn Go into Haskell. It offers a pragmatic approach: you use functional patterns where they truly simplify the code while retaining the familiar Go syntax. mo is especially useful for error handling, working with optional values, function composition, and implementing data processing pipelines. It works well with goroutines and channels, allowing you to build reliable concurrent programs.

\n\n

Installation

\n\n

Installing the mo library is done in the standard Go way using the go get package manager. Run the following command in the terminal at the root of your project (where go.mod is located):

\n\n
go get github.com/samber/mo
\n\n

After executing this command, the library will be added to your go.mod file, and you will be able to import it into your source files. Make sure you have Go version 1.18 or higher installed (required for generics support).

\n\n

Quick Start

\n\n

Let's start with a classic example — safe division of two numbers. In traditional Go, we would return an error. With mo, we use the Result type, which can be either Ok (success) or Err (error).

\n\n
package main\n\nimport (\n    "fmt"\n    "github.com/samber/mo"\n)\n\n// safeDivide returns a Result that contains either the division result or an error.\nfunc safeDivide(a, b float64) mo.Result[float64] {\n    if b == 0 {\n        return mo.Err[float64](fmt.Errorf("division by zero"))\n    }\n    return mo.Ok(a / b)\n}\n\nfunc main() {\n    result := safeDivide(10, 2)\n\n    // Use the Match method to handle both cases.\n    result.Match(\n        func(value float64) {\n            fmt.Printf("Result: %.2f\\n", value)\n        },\n        func(err error) {\n            fmt.Printf("Error: %s\\n", err)\n        },\n    )\n\n    // Try division by zero.\n    result2 := safeDivide(10, 0)\n    result2.Match(\n        func(value float64) {\n            fmt.Printf("Result: %.2f\\n", value)\n        },\n        func(err error) {\n            fmt.Printf("Error: %s\\n", err)\n        },\n    )\n}
\n\n

This example demonstrates the basic idea: instead of checking the error manually, we delegate the handling responsibility to the library using the Match method.

\n\n

Main Methods and Functions

\n\n

Below are the key components of the mo library. We will cover 8 main methods/types that will cover 90% of your needs.

\n\n

1. mo.Ok[T any] and mo.Err[T any]

\n

Signature:

\n
    \n
  • func Ok[T any](value T) Result[T]
  • \n
  • func Err[T any](err er

Recommendations