Skills Agentes

Golang Samber Mo

Tipos monádicos para Golang con samber/mo — Option, Result, Either, Future, IO, Task y State para valores nulos seguros, manejo de errores y composición funcional.

Reemplaza a: Manejo de errores con (T, error) y punteros nil

Solicitaread edit write glob grep bash(go:*) bash(golangci-lint:*) bash(git:*) agent webfetch mcp__context7__resolve-library-id mcp__context7__query-docs askuserquestion bash(godig:*) bash(gopls:*) lsp mcp__gopls__*
Estrellas
3.3k

en todo el repo

Actividad
57

0–100, la ruta de este skill

Actualizado
hace 2 meses

último commit aquí

Commits
4

últimos 90 días

Contexto
2.8k tok

94 tok en reposo

Paquete
8 archivos

66 KB

Instalar

Funciona con cualquier agente que lea SKILL.md

npx -y skills add samber/cc-skills-golang --skill golang-samber-mo --agent claude-code

Se instala solo en este repositorio.

Qué hace

  • Introduce tipos monádicos de samber/mo (Option, Result, Either, Future, IO, Task, State) para valores nulos, manejo de errores y composición funcional
  • Aplica Do notation (mo.Do) para estilo imperativo con seguridad monádica, capturando pánicos de MustGet
  • Elige entre métodos directos (.Map, .FlatMap) y funciones de sub-paquete (option.Map, result.Pipe3) según cambie o no el tipo

Úsalo cuando

  • Al usar o adoptar samber/mo
  • Cuando el código importa github.com/samber/mo
  • Al considerar patrones de programación funcional como diseño de seguridad en Golang

No lo uses cuando

    Qué lo activa

    Di cualquiera de estas frases y el agente debería cargar este skill.

    • “Ayúdame a usar mo.Option en vez de punteros nil en este struct”
    • “Necesito convertir (T, error) a Result[T] con samber/mo”
    • “¿Cómo encadeno Map y FlatMap cuando cambia el tipo con samber/mo?”

    SKILL.md

    En inglés

    Persona: You are a Go engineer bringing functional programming safety to Go. You use monads to make impossible states unrepresentable — nil checks become type constraints, error handling becomes composable pipelines.

    Thinking mode: Use ultrathink when designing multi-step Option/Result/Either pipelines. Wrong type choice creates unnecessary wrapping/unwrapping that defeats the purpose of monads.

    samber/mo — Monads and Functional Abstractions for Go

    Go 1.18+ library providing type-safe monadic types with zero dependencies. Inspired by Scala, Rust, and fp-ts.

    Official Resources:

    This skill is not exhaustive. Please refer to library documentation and code examples for more information. For Go package docs, symbols, versions, importers, and known vulnerabilities, → See samber/cc-skills-golang@golang-pkg-go-dev skill (godig) — prefer it over Context7 for Go package facts. To navigate this library's usage in your own code (definitions, call sites, diagnostics), → See samber/cc-skills-golang@golang-gopls skill (gopls). Context7 remains a fallback for docs not indexed on pkg.go.dev.

    go get github.com/samber/mo
    

    For an introduction to functional programming concepts and why monads are valuable in Go, see Monads Guide.

    Core Types at a Glance

    Type Purpose Think of it as...
    Option[T] Value that may be absent Rust's Option, Java's Optional
    Result[T] Operation that may fail Rust's Result<T, E>, replaces (T, error)
    Either[L, R] Value of one of two types Scala's Either, TypeScript discriminated union
    EitherX[L, R] Value of one of X types Scala's Either, TypeScript discriminated union
    Future[T] Async value not yet available JavaScript Promise
    IO[T] Lazy synchronous side effect Haskell's IO
    Task[T] Lazy async computation fp-ts Task
    State[S, A] Stateful computation Haskell's State monad

    Option[T] — Nullable Values Without nil

    Represents a value that is either present (Some) or absent (None). Eliminates nil pointer risks at the type level.

    import "github.com/samber/mo"
    
    name := mo.Some("Alice")          // Option[string] with value
    empty := mo.None[string]()        // Option[string] without value
    fromPtr := mo.PointerToOption(ptr) // nil pointer -> None
    
    // Safe extraction
    name.OrElse("Anonymous")  // "Alice"
    empty.OrElse("Anonymous")  // "Anonymous"
    
    // Transform if present, skip if absent
    upper := name.Map(func(s string) (string, bool) {
        return strings.ToUpper(s), true
    })
    

    Key methods: Some, None, Get, MustGet, OrElse, OrEmpty, Map, FlatMap, Match, ForEach, ToPointer, IsPresent, IsAbsent.

    Option implements json.Marshaler/Unmarshaler, sql.Scanner, driver.Valuer — use it directly in JSON structs and database models.

    For full API reference, see Option Reference.

    Result[T] — Error Handling as Values

    Represents success (Ok) or failure (Err). Equivalent to Either[error, T] but specialized for Go's error pattern.

    // Wrap Go's (value, error) pattern
    result := mo.TupleToResult(os.ReadFile("config.yaml"))
    
    // Same-type transform — errors short-circuit automatically
    upper := mo.Ok("hello").Map(func(s string) (string, error) {
        return strings.ToUpper(s), nil
    })
    // Ok("HELLO")
    
    // Extract with fallback
    val := upper.OrElse("default")
    

    Go limitation: Direct methods (.Map, .FlatMap) cannot change the type parameter — Result[T].Map returns Result[T], not Result[U]. Go methods cannot introduce new type parameters. For type-changing transforms (e.g. Result[[]byte] to Result[Config]), use sub-package functions or mo.Do:

    import "github.com/samber/mo/result"
    
    // Type-changing pipeline: []byte -> Config -> ValidConfig
    parsed := result.Pipe2(
        mo.TupleToResult(os.ReadFile("config.yaml")),
        result.Map(func(data []byte) Config { return parseConfig(data) }),
        result.FlatMap(func(cfg Config) mo.Result[ValidConfig] { return validate(cfg) }),
    )
    

    Key methods: Ok, Err, Errf, TupleToResult, Try, Get, MustGet, OrElse, Map, FlatMap, MapErr, Match, ForEach, ToEither, IsOk, IsError.

    For full API reference, see Result Reference.

    Either[L, R] — Discriminated Union of Two Types

    Represents a value that is one of two possible types. Unlike Result, neither side implies success or failure — both are valid alternatives.

    // API that returns either cached data or fresh data
    func fetchUser(id string) mo.Either[CachedUser, FreshUser] {
        if cached, ok := cache.Get(id); ok {
            return mo.Left[CachedUser, FreshUser](cached)
        }
        return mo.Right[CachedUser, FreshUser](db.Fetch(id))
    }
    
    // Pattern match
    result := fetchUser("user-123")
    result.Match(
        func(cached CachedUser) mo.Either[CachedUser, FreshUser] { /* use cached */ },
        func(fresh FreshUser) mo.Either[CachedUser, FreshUser] { /* use fresh */ },
    )
    

    When to use Either vs Result: Use Result[T] when one path is an error. Use Either[L, R] when both paths are valid alternatives (cached vs fresh, left vs right, strategy A vs B).

    Either3[T1, T2, T3], Either4, and Either5 extend this to 3-5 type variants.

    For full API reference, see Either Reference.

    Do Notation — Imperative Style with Monadic Safety

    mo.Do wraps imperative code in a Result, catching panics from MustGet() calls:

    result := mo.Do(func() int {
        // MustGet panics on None/Err — Do catches it as Result error
        a := mo.Some(21).MustGet()
        b := mo.Ok(2).MustGet()
        return a * b  // 42
    })
    // result is Ok(42)
    
    result := mo.Do(func() int {
        val := mo.None[int]().MustGet()  // panics
        return val
    })
    // result is Err("no such element")
    

    Do notation bridges imperative Go style with monadic safety — write straight-line code, get automatic error propagation.

    Pipeline Sub-Packages vs Direct Chaining

    samber/mo provides two ways to compose operations:

    Direct methods (.Map, .FlatMap) — work when the output type equals the input type:

    opt := mo.Some(42)
    doubled := opt.Map(func(v int) (int, bool) {
        return v * 2, true
    })  // Option[int]
    

    Sub-package functions (option.Map, result.Map) — required when the output type differs from input:

    import "github.com/samber/mo/option"
    
    // int -> string type change: use sub-package Map
    strOpt := option.Map(func(v int) string {
        return fmt.Sprintf("value: %d", v)
    })(mo.Some(42))  // Option[string]
    

    Pipe functions (option.Pipe3, result.Pipe3) — chain multiple type-changing transformations readably:

    import "github.com/samber/mo/option"
    
    result := option.Pipe3(
        mo.Some(42),
        option.Map(func(v int) string { return strconv.Itoa(v) }),
        option.Map(func(s string) []byte { return []byte(s) }),
        option.FlatMap(func(b []byte) mo.Option[string] {
            if len(b) > 0 { return mo.Some(string(b)) }
            return mo.None[string]()
        }),
    )
    

    Rule of thumb: Use direct methods for same-type transforms. Use sub-package functions + pipes when types change across steps.

    For detailed pipeline API reference, see Pipelines Reference.

    Common Patterns

    JSON API responses with Option

    type UserResponse struct {
        Name     string            `json:"name"`
        Nickname mo.Option[string] `json:"nickname"`  // omits null gracefully
        Bio      mo.Option[string] `json:"bio"`
    }
    

    Database nullable columns

    type User struct {
        ID       int
        Email    string
        Phone    mo.Option[string]  // implements sql.Scanner + driver.Valuer
    }
    
    err := row.Scan(&u.ID, &u.Email, &u.Phone)
    

    Wrapping existing Go APIs

    // Convert map lookup to Option
    func MapGet[K comparable, V any](m map[K]V, key K) mo.Option[V] {
        return mo.TupleToOption(m[key])  // m[key] returns (V, bool)
    }
    

    Uniform extraction with Fold

    mo.Fold works uniformly across Option, Result, and Either via the Foldable interface:

    str := mo.Fold[error, int, string](
        mo.Ok(42),  // works with Option, Result, or Either
        func(v int) string { return fmt.Sprintf("got %d", v) },
        func(err error) string { return "failed" },
    )
    // "got 42"
    

    Best Practices

    1. Prefer OrElse over MustGet — MustGet panics on absent/error values; use it only inside mo.Do blocks where panics are caught, or when you are certain the value exists
    2. Use TupleToResult at API boundaries — convert Go's (T, error) to Result[T] at the boundary, then chain with Map/FlatMap inside your domain logic
    3. Use Result[T] for errors, Either[L, R] for alternatives — Result is specialized for success/failure; Either is for two valid types
    4. Option for nullable fields, not zero values — Option[string] distinguishes "absent" from "empty string"; use plain string when empty string is a valid value
    5. Chain, don't nest — result.Map(...).FlatMap(...).OrElse(default) reads left-to-right; avoid nested if/else patterns when monadic chaining is cleaner
    6. Use sub-package pipes for multi-step type transformations — when 3+ steps each change the type, option.Pipe3(...) is more readable than nested function calls

    For advanced types (Future, IO, Task, State), see Advanced Types Reference.

    If you encounter a bug or unexpected behavior in samber/mo, open an issue at https://github.com/samber/mo/issues.

    Cross-References

    • -> See samber/cc-skills-golang@golang-samber-lo skill for functional collection transforms (Map, Filter, Reduce on slices) that compose with mo types
    • -> See samber/cc-skills-golang@golang-error-handling skill for idiomatic Go error handling patterns
    • -> See samber/cc-skills-golang@golang-safety skill for nil-safety and defensive Go coding
    • -> See samber/cc-skills-golang@golang-database skill for database access patterns
    • -> See samber/cc-skills-golang@golang-design-patterns skill for functional options and other Go patterns

    Reproducido de samber/cc-skills-golang bajo licencia MIT. Leer esta página en markdown.

    Archivos

    8 archivos en el paquete. Solo se lee SKILL.md al activarse — las referencias se cargan si el skill decide que las necesita.

    Antes de instalar

    Requiere Go 1.18+ y el binario `go`; instalar con `go get github.com/samber/mo`.

    Detalles

    Creador
    samber
    Licencia
    MIT
    Recursos incluidos
    referencias
    Código fuente
    Ver SKILL.md

    Etiquetas

    Más de samber/cc-skills-golang

    Este repo incluye 46 skills. Si instalas uno, normalmente ya tienes los demás. Ver el pack cc-skills-golang entero y su comando de instalación

    Buenas prácticas de linting y configuración de golangci-lint para proyectos Golang: ejecutar linters, configurar .golangci.yml, suprimir avisos con nolint, interpretar salidas y elegir linters.

    Costo de contexto al activarse
    1.8k tok
    Tamaño del paquete
    5 archivos
    Última actualización
    el mes pasado
    herramientas desarrollo

    Benchmarking, profiling y medición de rendimiento en Golang: escribir y comparar benchmarks, perfilar con pprof, analizar con benchstat y detectar regresiones en CI.

    Costo de contexto al activarse
    3.3k tok
    Tamaño del paquete
    10 archivos
    Última actualización
    hace 2 meses
    testing qa

    Orquestador de skills de Golang, siempre activo en cualquier tarea de código, revisión, debug o setup: carga las skills más relevantes de samber/cc-skills-golang, a menudo varias a la vez.

    Costo de contexto al activarse
    3.8k tok
    Tamaño del paquete
    4 archivos
    Última actualización
    hace 2 meses
    herramientas desarrollo

    Patrones y metodología de optimización de rendimiento en Golang: si hay cuello de botella X, aplica el patrón Y, una vez que profiling o benchmarks ya lo identificaron.

    Costo de contexto al activarse
    2.3k tok
    Tamaño del paquete
    9 archivos
    Última actualización
    hace 2 meses
    herramientas desarrollo

    Tests de Golang listos para producción: table-driven, suites y mocks con testify, tests paralelos, fuzzing, fixtures, detección de fugas de goroutines con goleak, snapshot testing, cobertura, tests de integración.

    Costo de contexto al activarse
    4.4k tok
    Tamaño del paquete
    6 archivos
    Última actualización
    hace 2 meses
    testing qa

    Inyección de dependencias en Golang con samber/do: contenedores de servicios, gestión de ciclo de vida, scopes, health checks, apagado ordenado y organización en módulos.

    Costo de contexto al activarse
    2.3k tok
    Tamaño del paquete
    4 archivos
    Última actualización
    hace 2 meses
    herramientas desarrollo

    Skills relacionados

    Desarrollo de aplicaciones CLI en Go: estructura de comandos, flags, configuración por capas, versión embebida, exit codes, señales, completions y testing con cobra, viper o urfave/cli.

    Costo de contexto al activarse
    2.6k tok
    Tamaño del paquete
    14 archivos
    Última actualización
    hace 4 meses
    herramientas desarrollo

    Convenciones de estilo en Golang: longitud y corte de líneas, declaración de variables, claridad del control de flujo y cuándo los comentarios ayudan u estorban.

    Costo de contexto al activarse
    2.5k tok
    Tamaño del paquete
    3 archivos
    Última actualización
    hace 2 meses
    herramientas desarrollo

    Patrones de concurrencia en Go: úsalo al escribir o revisar código concurrente con goroutines, channels, select, locks, sync primitives, errgroup, singleflight, worker pools o pipelines fan-out/fan-in.

    Costo de contexto al activarse
    2.3k tok
    Tamaño del paquete
    5 archivos
    Última actualización
    hace 2 meses
    herramientas desarrollo