Library mo for Go: Monads and Functional Patterns
\n\nWelcome 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.
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.
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.
Installation
\n\nInstalling 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):
go get github.com/samber/mo\n\nAfter 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).
Quick Start
\n\nLet'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).
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\nThis example demonstrates the basic idea: instead of checking the error manually, we delegate the handling responsibility to the library using the Match method.
Main Methods and Functions
\n\nBelow are the key components of the mo library. We will cover 8 main methods/types that will cover 90% of your needs.
1. mo.Ok[T any] and mo.Err[T any]
\nSignature:
\n- \n
func Ok[T any](value T) Result[T]\n func Err[T any](err er
Also in library
Parsing HTML in Swift (iOS/macOS): SwiftSoup and Fuzi Libraries
openai-api-rs for Rust: Complete Guide with Code Examples
Knex.js for JavaScript (Node.js): Complete Guide with Examples