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
3k

en todo el repo

Actividad
57

0–100, la ruta de este skill

Actualizado
el mes pasado

ú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 MustGetMustGet 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 valuesOption[string] distinguishes "absent" from "empty string"; use plain string when empty string is a valid value
    5. Chain, don't nestresult.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.

    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
    hace 3 días
    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 28 días
    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 20 días
    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
    el mes pasado
    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
    el mes pasado
    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 22 días
    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 3 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
    el mes pasado
    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
    el mes pasado
    herramientas desarrollo