cast

package module
v2.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 15, 2026 License: MIT Imports: 5 Imported by: 0

README

cast

Now with Generics!

Release GoDoc Go Report Card Github issues Github pull requests MIT

CHANGELOG - This project adheres to Semantic Versioning. You should expect API stability in Minor and Patch version releases

Mature Code has proven satisfactory and is in wide production use, cleanup of the underlying code may cause some minor changes. Backwards-compatibility is guaranteed.

This project is inspired by spf13/cast. More about cast.

Table of Contents

What is Cast?

cast is a library to easily convert between different data types in a straightforward and predictable way. It provides a generic function to easily convert both simple types (number to a string, interface to a bool, etc.) and complex types (slice to map, any to func() any, any to chan any, etc.). Cast does this intelligently when an obvious conversion is possible and logically when a conversion requires a predictable measurable process.

A concrete example: casting "6.789" to int yields 6, not 7. Cast converts to float64 first, then calls math.Floor() — because there is no integer that is almost 7, but there is a 6 that can be contained within the original value.

The primary use-case is consuming untyped or loosely typed data from external sources (YAML, TOML, JSON, API responses) without repetitive type-assertion boilerplate.

Go version support
Release Date Min Go
v2.1.4 2026-05-14 1.21
v2.1.3 2026-05-13 1.21
v2.1.2 2026-05-13 1.21
v2.1.1 2026-05-04 1.21
v2.1.0 2026-04-20 1.21
v2.0.5 2025-11-12 1.24
v2.0.4 2025-11-03 1.24
v2.0.3 2024-02-22 1.21
v2.0.2 2023-12-30 1.18
v2.0.1 2023-12-28 1.18
v2.0.0 2023-12-23 1.18
v1.0.2 2020-06-25 1.14
v1.0.1 2020-06-25 1.14
v1.0.0 2020-05-02 1.14

Usage

// To returns the cast value; errors are silently dropped (zero value returned on failure).
func To[T Types](v any, o ...Op) T

// ToE returns the cast value and any error.
func ToE[T Types](v any, o ...Op) (T, error)

T in To/ToE is constrained to cast.Types, which covers all scalar types (bool, int*, uint*, float*, complex*, string), []T slices, map[K]V maps, chan T channels, cast.Func[T] closures, struct types, and stdlib named types (time.Time, time.Duration, net.IP, *url.URL, *regexp.Regexp, *big.Int, *big.Float). Named types with a matching underlying kind also satisfy Types (e.g. type Celsius float32).

On error, To returns the zero value for T; ToE returns the zero value plus the error. Use ToE when you need to distinguish a successful zero-value cast from a failed one.

Supported Conversions
cast.To[T](v, opts...)   // T; drops errors (zero value on failure)
cast.ToE[T](v, opts...)  // (T, error)

T covers all scalars, named underlying types (type Celsius float32), []T slices, map[K]V maps, chan T channels, cast.Func[T] closures, and struct types. Struct hydration also goes through cast.To[T] / cast.ToE[T].

[!IMPORTANT] Things that may surprise you

  • Float → int truncates, it doesn't round1.9 → 1, -1.9 → -1
  • stringbool: strconv.ParseBool first, then integer fallback"yes", "on", and similar are not accepted, but any string that parses as a non-zero integer is true ("-1"true, "1.5"true, "0.1"false because floor(0.1) = 0)
  • Negative → uint* errors — use Op{ABS, true} to use the absolute value instead; works for signed int, float, and numeric string sources

Legend: always succeeds · ~ succeeds for valid input · always errors

chan T and Func[T] succeed whenever source → T succeeds — the cast result is wrapped in a buffered channel or closure. Nesting is supported (chan []int, Func[chan int], etc.). any targets always succeed.

Source bool int* uint* float* · complex* string []T map[K]V struct
bool
int* (signed)
uint* (unsigned)
float* · complex* ~²³ ~¹² ✓³
string ~⁴ ~⁵ ~⁵ ~⁵ ~ⁿ
[]byte · []rune ~ ~ ~ ~ ✓⁶ ~ᵐ ~ᵐ
[]T · [N]T ~⁷ ✓⁸
map[K]V ~⁷ ~ᵇ
struct ~⁷ ✓⁹ ~ᵇ
nil
error · Stringer ~ᵃ ~ᵃ ~ᵃ ~ᵃ ✓ᵃ
any / interface
Named types† ~ ~ ~ ~

int* = int · int8 · int16 · int32 · int64  ·  uint* = uint · uint8 · uint16 · uint32 · uint64 · uintptr
float* = float32 · float64  ·  complex* = complex64 · complex128
† Named types: time.Time · time.Duration · net.IP · *url.URL · *regexp.Regexp · *big.Int · *big.Float — see Named-type targets; all implement fmt.Stringer, so casting from them follows the string-parse path.


Number conversions

¹ Negative signed or float → uint* errors by default. Pass Op{ABS, true} to use the absolute value instead.
² float/complex → int*: truncates toward zero — 1.9 → 1, -1.9 → -1. Does not round.
³ complex → int*/uint*/float*: the imaginary part is discarded; only the real component is used. complex64 sources carry float32 precision, so complex64 → float64 has the same precision loss as float32 → float64.

String conversions

stringbool: first tries strconv.ParseBool ("1"/"0"/"t"/"f"/"true"/"false" and their case variants); on failure falls back to integer parsing — any string that converts to a non-zero int is true, zero is false. "yes", "on", and similar are not accepted. Note that "0.1"false because floor(0.1) = 0.
string → numeric: parsed as float64 via strconv.ParseFloat; non-numeric strings error. Float strings truncate when targeting int*.
[]byte and []runestring: uses string(b) / string(r) directly — not element-wise and not JSON-encoded. Scalar targets work the same way, via this string representation.
⁷ Complex types, maps, and structs → string: stringified via fmt.Sprintf("%v", v).

Container conversions

[]T/[N]Tmap[K]V: element indices (0, 1, 2 …) become map keys, cast to key type K.
structmap[K]V: exported field names become keys; embedded structs are inlined; nested structs recurse into nested maps when the value type is any or map.
stringmap[K]V: succeeds when the string looks like a JSON object or array — decoded automatically. Non-JSON strings error.
error/Stringer → any target: calls .Error() or .String(), then parses the result the same way a plain string source would. Succeeds whenever the string value would succeed.
map/structstruct: source keys/fields matched case-sensitively to target exported fields. Unmatched fields retain their zero value; STRICT promotes mismatches to errors. Anonymous fields are promoted on both sides. Use To[T] / ToE[T] for arbitrary struct types.
ˡ string[]T: []byte and []rune use direct Go string conversion. All other element types attempt scalar wrap (e.g. "42"[]int{42}); if that fails and the string looks like a JSON collection, it is decoded automatically. Pass Op{DECODE, "json"} to force JSON decoding first.
[]byte ([]uint8) and []rune ([]int32) are treated as slices for container targets: elements are cast individually when converting to []T or map[K]V.
ˢ Non-collection sources wrap as single-element slices for []T targets: 42 → []int{42}. Structs iterate exported fields; maps iterate values; nil produces [zero_T].

Interface targets (error, fmt.Stringer) — the source must already implement the interface; no parsing occurs. Sources that don't implement the interface always error.

Named-type targets

time.Time, time.Duration, net.IP, *url.URL, *regexp.Regexp, *big.Int, and *big.Float are first-class cast targets via To[T] / ToE[T]. Any source that stringifies to a valid representation is accepted. All support the DEFAULT op and struct field hydration.

Source time.Time time.Duration net.IP *url.URL *regexp.Regexp *big.Int *big.Float
same named type ✓ᵃ ✓ᵃ
*time.Time ~ᵇ
time.Time (as source) ✓ʷ ✓ʷ
url.URL (value, not ptr)
big.Int · big.Float (values) ✓ᵗ ✓ᵗ ~ ✓ᶜ
*big.Float*big.Int ✓ᵗ ✓ᵗ ~ ~ᶜ
*big.Int*big.Float ✓ᵗ ✓ᵗ ~
int* · uint* ✓ᵈ ~ᵖ
float* ✓ᵉ ~ᶜ
string ~ᶠ ~ᵍ ~ ~ ~ ~
[]byte ~ᶠ ~ ~ⁱ ~ ~
uint32 ✓ᵈ ✓ⁱ
nil
any / interface

time.Time targets

int* / uint*time.Time: treated as Unix nanoseconds — time.Unix(0, n).UTC(). uint32 follows the same rule.
float*time.Time: treated as Unix seconds; fractional seconds preserved via nanosecond conversion.
string / []bytetime.Time: 19 formats tried in order — RFC3339Nano, RFC3339, DateTime, RFC1123Z, RFC1123, RFC822Z, RFC822, DateOnly, then Layout/ANSIC/UnixDate/RubyDate/RFC850/Kitchen/Stamp/StampMilli/StampMicro/StampNano/TimeOnly. The empty string "" is a special case: time.Parse("", "") succeeds and returns the zero time.Time{}.
*big.Int / big.Inttime.Time: treated as Unix nanoseconds — time.Unix(0, n), matching int* sources. *big.Float / big.Floattime.Time: treated as Unix seconds with fractional precision, matching float* sources. → time.Duration: as nanoseconds (*big.Int must fit in int64; *big.Float truncated toward zero). → net.IP: zero-padded to 16 bytes big-endian as IPv6; negative or > 128-bit values error.
ʷ time.Time (as source) → *big.Int: stored as Unix nanoseconds (val.UnixNano()), matching the nanosecond unit that *big.Int → time.Time uses; the round-trip is lossless for times within int64 range. → *big.Float: stored as Unix seconds with fractional precision (val.Unix() + val.Nanosecond()/1e9), matching the unit that *big.Float → time.Time uses.

net.IP targets

uint32 / int32net.IP: packed big-endian IPv4 — net.IPv4(b3, b2, b1, b0). int32 must be non-negative. []byte of exactly 4 or 16 bytes: direct copy into net.IP; other lengths parsed as string.
ᵖ Among int*, only int32net.IP is supported; other sizes error. For uint*, only uint32 has a dedicated IPv4 path; other sizes fall through to string-parse.

*big.Int / *big.Float targets

ᵃ Same-type cast returns an independent copy — new(big.Int).Set(src) / new(big.Float).Copy(src).
*big.Float / big.Float / float**big.Int: truncated toward zero. NaN/±Inf inputs error.
ʰ string*big.Int: base auto-detected — 0x hex, 0o octal, 0b binary, decimal otherwise.

General

*time.Timetime.Time: dereferenced when non-nil; nil pointer errors.
stringtime.Duration: time.ParseDuration — accepts "ns", "µs"/"us", "ms", "s", "m", "h" and combinations (e.g. "1h30m45s").
ʲ Via toString fallback — any source that successfully stringifies is passed to the string-parse path. *url.URL almost always succeeds (url.Parse is very permissive). *regexp.Regexp succeeds whenever the stringified form is a valid regexp pattern.

Options

Both functions accept optional Op values that control conversion behavior. Each Op carries a Flag constant and a value. Multiple options may be passed:

result := cast.To[float32](val, cast.Op{cast.DEFAULT, float32(3.14)})

items := []any{1, "two", true, 1}
result, err := cast.ToE[[]string](items, cast.Op{cast.UNIQUE_VALUES, true})
// result = []string{"1", "two", "true"}  (duplicate 1 removed)

Available flags

Flags are either global or local. Global flags propagate into nested casts (e.g. into element-level conversions inside []T or map[K]V). Local flags apply only at the outermost call and are stripped before any nested casts.

Flag Type Scope Applies to Effect
DEFAULT target type T local all targets Return this value on error instead of the zero value. Val must be the exact same type as T — a wrong-typed DEFAULT causes an immediate error before the input is inspected, even for inputs that would otherwise succeed.
ABS bool global uint* targets Use absolute value when the source is negative instead of erroring. Applies to signed integer sources (int, int8int64), float sources (float32, float64), and numeric string sources that parse to a negative value.
DECODE string local bool, int*, uint*, float*, complex*, []T (string/error/Stringer source) Decode the source string as the specified format before converting; only "json" is supported. For scalar targets it fires as a fallback after normal parsing fails (e.g. "\"1\""1). For []T it forces JSON decoding first, bypassing []byte/[]rune special-casing. Note: map[K]V already auto-decodes JSON-like strings without this flag.
DUPLICATE_KEY_ERROR bool local map[K]V from map Error when two source keys cast to the same target key
FORMAT string global time.Time (string or []byte source) Use this exact time.Parse layout instead of trying the 19 built-in formats (e.g. "2006/01/02"). When set, the default format list is skipped entirely. Without FORMAT, the empty string "" is a valid source that returns the zero time.Time{}.
JSON bool global string target JSON-encode the resulting string (adds quotes and escaping). Because JSON is global it also applies to string elements inside []string, map[K]string, etc.
LENGTH int global []T, chan T Pre-allocate slice capacity (≥ 0) or set channel buffer size (≥ 1). Because LENGTH is global, for composite types like chan []int a single LENGTH value controls both the channel buffer and the inner slice capacity.
PRIVATE bool global struct source → map; map/struct → struct target Include unexported fields when reading a struct source or hydrating a struct target. Propagates to nested struct conversions at all levels.
STRICT bool global struct source → map; map/struct → struct target Error instead of silently skipping unconvertible fields or unmatched keys. Propagates to nested struct conversions.
UNIQUE_VALUES bool global []T Deduplicate after conversion, preserving first-seen order. Because UNIQUE_VALUES is global, for nested slice types like [][]int every level is deduplicated independently.

Global flag propagation — Global flags propagate through the entire conversion tree via ops.Global(). Every element-level cast inside a container receives the same global flags as the outer call. Practical consequences:

// ABS propagates: every element in []uint is absolute-valued
cast.To[[]uint]([]int{-5, 3, -1}, cast.Op{cast.ABS, true})         // []uint{5, 3, 1}

// JSON propagates: every string element is JSON-encoded
cast.To[[]string]([]int{1, 2}, cast.Op{cast.JSON, true})             // []string{`"1"`, `"2"`}

// LENGTH propagates: sets both channel buffer and inner slice capacity
cast.ToE[chan []int]([]string{"a","b"}, cast.Op{cast.LENGTH, 10})    // chan (buf 10) of []int (cap 10)

// UNIQUE_VALUES propagates: each inner []int is independently deduplicated
cast.To[[][]int]([][]int{{1,2,1},{3,3}}, cast.Op{cast.UNIQUE_VALUES, true}) // [][]int{{1,2},{3}}

// FORMAT propagates: every element parsed with the custom layout
cast.To[[]time.Time]([]string{"2024/04/22"}, cast.Op{cast.FORMAT, "2006/01/02"})
Examples
Scalars
Bool

Only specific string values are accepted; "yes", "on", and similar are not supported.

cast.To[bool](1)       // true
cast.To[bool](0)       // false
cast.To[bool]("true")  // true  — also "TRUE", "True", "t", "T", "1"
cast.To[bool]("false") // false — also "FALSE", "False", "f", "F", "0"
cast.To[bool]("yes")   // false — "yes"/"no"/"on"/"off" are not accepted
cast.To[bool](nil)     // false
Int and Float

Float-to-int truncates toward zero via math.Floor; it does not round.

cast.To[int](8.31)   // 8   — Floor, not round
cast.To[int]("8.51") // 8   — string → float64 → Floor
cast.To[int](true)   // 1
cast.To[int](nil)    // 0

// Negative → unsigned: errors by default; ABS takes the absolute value instead.
// ABS works for signed int, float, and numeric string sources.
cast.To[uint](-5)                                    // 0 (error silently dropped)
cast.To[uint](-5, cast.Op{cast.ABS, true})           // 5
cast.To[uint](float64(-3.9), cast.Op{cast.ABS, true}) // 3 (floor of 3.9)
cast.To[uint]("-7.5", cast.Op{cast.ABS, true})        // 7 (floor of 7.5)
String
cast.To[string](8)                  // "8"
cast.To[string](8.31)               // "8.31"
cast.To[string]([]byte("hi"))       // "hi" — string(b) directly, not element-wise
cast.To[string](true)               // "true"
cast.To[string](nil)                // ""

// JSON-encode the result (adds quotes and escaping)
jsonStr, _ := cast.ToE[string](`hello "world"`, cast.Op{cast.JSON, true})
// jsonStr = `"hello \"world\""`
Slices

Slices, arrays, and maps convert element-wise. Scalar sources, nil, structs, and error/Stringer values are wrapped as single-element slices. nil always produces [zero_T].

cast.To[[]int]([]string{"1", "2", "3"})           // []int{1, 2, 3}
cast.To[[]string]([]int{1, 2, 3})                 // []string{"1", "2", "3"}
cast.To[[]bool]([]int{1, 0, 1})                   // []bool{true, false, true}

// Scalar sources wrap as single-element slices
cast.To[[]int](42)        // []int{42}
cast.To[[]string](3.14)   // []string{"3.14"}
cast.To[[]int](nil)       // []int{0}  — nil produces [zero_T]

// Map source: map values become slice elements; iteration order is undefined
cast.To[[]string](map[string]int{"a": 1, "b": 2}) // []string{"1", "2"} (order varies)

// Struct source: exported field values become slice elements
type Point struct{ X, Y int }
cast.To[[]int](Point{X: 3, Y: 4})    // []int{3, 4}
cast.To[[]string](Point{X: 3, Y: 4}) // []string{"3", "4"}

// DECODE=json for scalars: fallback after normal parse fails
// `"1"` is a JSON-encoded string containing "1", which then parses to 1
cast.To[int](`"1"`, cast.Op{cast.DECODE, "json"})              // 1
cast.To[float64](`"1.5"`, cast.Op{cast.DECODE, "json"})        // 1.5
cast.To[bool](`"true"`, cast.Op{cast.DECODE, "json"})          // true

// DECODE=json for slices: decode a JSON array/object string before converting
cast.To[[]int](`[1, 2, 3]`, cast.Op{cast.DECODE, "json"})      // []int{1, 2, 3}
cast.To[[]string](`["a","b"]`, cast.Op{cast.DECODE, "json"})   // []string{"a", "b"}

// UNIQUE_VALUES: deduplicate after conversion, preserving first-seen order
cast.ToE[[]int]([]int{1, 2, 1, 3}, cast.Op{cast.UNIQUE_VALUES, true})
// []int{1, 2, 3}

// LENGTH: pre-allocate backing capacity
cast.ToE[[]int]([]string{"1", "2"}, cast.Op{cast.LENGTH, 100})
Maps
// map → map: keys and values are individually cast to the target types
cast.ToE[map[string]int](map[string]string{"a": "1", "b": "2"})
// map[string]int{"a": 1, "b": 2}

// struct → map: exported field names become keys; embedded structs are inlined
type Point struct{ X, Y int }
cast.ToE[map[string]any](Point{X: 3, Y: 4})
// map[string]any{"X": 3, "Y": 4}

// slice/array → map: element indices become keys
cast.ToE[map[int]string]([]string{"a", "b", "c"})
// map[int]string{0: "a", 1: "b", 2: "c"}

// Options
cast.ToE[map[string]any](myStruct,
    cast.Op{cast.PRIVATE, true},             // include unexported fields
    cast.Op{cast.STRICT, true},              // error on unconvertible fields
    cast.Op{cast.DUPLICATE_KEY_ERROR, true}, // error on duplicate keys (map→map)
)
Structs

To[T] / ToE[T] hydrate a struct from a map or another struct when T is a struct type. Field matching is case-sensitive on exported field names. Fields with no matching source key retain their zero value.

type Point struct {
    X int
    Y int
}

// From a map: values are cast to each field's type
point, _ := cast.ToE[Point](map[string]any{"X": 3, "Y": "4"})
// Point{X: 3, Y: 4}

// From another struct: matched by exported field name; extra source fields are ignored
type Src struct{ X, Y, Z int }
pointFromStruct, _ := cast.ToE[Point](Src{X: 10, Y: 20, Z: 30})
// Point{X: 10, Y: 20}  — Z ignored, no matching field

// STRICT: error when source has keys with no matching target field
_, strictErr := cast.ToE[Point](
    map[string]any{"X": 1, "Y": 2, "Z": 3},
    cast.Op{cast.STRICT, true},
)
// strictErr != nil — "Z" has no matching field in Point

// To[T] drops the error and returns the zero value on failure
pointFromMap := cast.To[Point](map[string]any{"X": 5, "Y": 6})
// Point{X: 5, Y: 6}
Field key resolution

The lookup key for each target field follows this priority: a cast: struct tag first, then the name portion of a json: tag (options like omitempty are stripped), then the bare field name. A tag value of "-" skips the field entirely. The same resolution applies when the source is another struct.

type Config struct {
    Host string `cast:"host"`           // matched by key "host"
    Port int    `json:"port,omitempty"` // matched by key "port"
    Skip string `cast:"-"`             // never populated from any source
}
cfg, _ := cast.ToE[Config](map[string]any{"host": "localhost", "port": 8080})
// Config{Host: "localhost", Port: 8080}

// Struct source: source field keys follow the same tag priority
type Src struct {
    Host string `cast:"host"`
    Port int    `json:"port"`
}
cfg2, _ := cast.ToE[Config](Src{Host: "db", Port: 5432})
// Config{Host: "db", Port: 5432}
Unexported fields (PRIVATE)

Unexported fields are skipped in both the source and target by default. Set PRIVATE to read unexported source fields and hydrate unexported target fields.

type connConfig struct {
    host string
    port int
}

// From a map
conn, _ := cast.ToE[connConfig](
    map[string]any{"host": "localhost", "port": 8080},
    cast.Op{cast.PRIVATE, true},
)
// connConfig{host: "localhost", port: 8080}

// From a struct with unexported source fields
type Src struct{ host string; port int }
conn2, _ := cast.ToE[connConfig](Src{host: "db", port: 5432}, cast.Op{cast.PRIVATE, true})
// connConfig{host: "db", port: 5432}
Channels and Funcs

chan T returns a buffered channel (buffer size 1) pre-loaded with the cast value. cast.Func[T] returns a func() T closure.

// Channel
ten := <-cast.To[chan int]("10")  // 10

// Custom buffer size (≥ 1)
intCh, _ := cast.ToE[chan int](42, cast.Op{cast.LENGTH, 10})

// Func: cast.Func[T] is a named type (type Func[T] func() T);
// a named type is required because Go generics do not accept plain function literals
// as type parameters.
intFunc := cast.To[cast.Func[int]]("10")
fmt.Println(intFunc()) // 10

// Nested composite types are supported
sliceCh    := cast.To[chan []int]([]int{1, 2, 3}) // chan []int
nestedFunc := cast.To[cast.Func[chan int]](42)    // func() chan int
Named types

time.Time, time.Duration, net.IP, *url.URL, *regexp.Regexp, *big.Int, and *big.Float are direct cast targets via To[T] / ToE[T]. See Named-type targets for the full source compatibility matrix.

// time.Time — string (19 formats tried), int/uint (Unix nanoseconds), float (Unix seconds)
rfcTime, _    := cast.ToE[time.Time]("2024-04-22T12:00:00Z")          // RFC3339
dateTime, _   := cast.ToE[time.Time]("2024-04-22")                    // DateOnly
unixNsTime    := cast.To[time.Time](int64(1_713_787_200_000_000_000)) // 2024-04-22 (Unix ns)
unixSecTime   := cast.To[time.Time](float64(1713787200.5))             // Unix seconds (fractional)

// time.Duration — time.ParseDuration syntax, or int/float as nanoseconds
duration, _  := cast.ToE[time.Duration]("1h30m45s")
fiveSeconds  := cast.To[time.Duration](int64(5000000000)) // 5s (as ns)

// net.IP — string (IPv4 or IPv6), uint32 (packed IPv4), []byte (4 or 16 bytes)
localIP, _  := cast.ToE[net.IP]("192.168.1.1")
packedIP    := cast.To[net.IP](uint32(0xC0A80101)) // 192.168.1.1 packed

// *url.URL
pageURL, _ := cast.ToE[*url.URL]("https://example.com/path?q=1")

// *regexp.Regexp
fooPattern, _ := cast.ToE[*regexp.Regexp](`^foo\d+$`)

// *big.Int — string auto-detects base: 0x hex, 0o octal, 0b binary, decimal
hexInt, _    := cast.ToE[*big.Int]("0xFF")      // 255
binaryInt, _ := cast.ToE[*big.Int]("0b1010")    // 10
bigFromInt   := cast.To[*big.Int](int64(12345))

// *big.Float — arbitrary precision; float64 sources are limited to float64 precision
bigPi, _ := cast.ToE[*big.Float]("3.14159265358979323846264338327")
Interface targets

error, fmt.Stringer, and github.com/bdlm/std/v2/errors.Error can be cast targets, but only when the source already implements the interface. The value is returned as-is; no string parsing occurs.

myErr := fmt.Errorf("something failed")
cast.To[error](myErr)      // returns myErr unchanged
cast.ToE[error](myErr)     // (myErr, nil)
cast.ToE[error](42)        // (nil, error) — int does not implement error
cast.ToE[fmt.Stringer](42) // (nil, error) — int does not implement fmt.Stringer
Error handling

To drops errors and returns the zero value. ToE returns both the value and the error. Use DEFAULT to substitute a custom fallback on error.

cast.To[int]("Hi!")                 // 0  — error silently dropped
result, err := cast.ToE[int]("Hi!") // 0, error: unable to cast "Hi!" of type string to int

// DEFAULT: return a custom value instead of zero on error
result := cast.To[int]("Hi!", cast.Op{cast.DEFAULT, -1})
// result = -1

Documentation

Overview

Package cast provides generic type conversion for Go 1.21+.

The two public entry points are To (ignores errors) and ToE (returns errors). Both accept an optional variadic Op list that controls conversion behavior; see Flag for available options.

Supported target types are described by the Types constraint: all basic scalar types, slices of scalars, channels of scalars/slices, maps, and Func wrappers for each of those groups.

Index

Examples

Constants

View Source
const (
	DEFAULT             = internal.DEFAULT
	ABS                 = internal.ABS
	DECODE              = internal.DECODE
	DUPLICATE_KEY_ERROR = internal.DUPLICATE_KEY_ERROR
	FORMAT              = internal.FORMAT
	JSON                = internal.JSON
	LENGTH              = internal.LENGTH
	PRIVATE             = internal.PRIVATE
	STRICT              = internal.STRICT
	UNIQUE_VALUES       = internal.UNIQUE_VALUES
)

Available option flags. See the internal package for full documentation.

Variables

View Source
var (
	// ErrorUnableToCast is a sentinel error returned when a value cannot be
	// cast to the requested type.
	ErrorUnableToCast = internal.ErrorUnableToCast

	// ErrorSignedToUnsigned is returned when a negative value is cast to an
	// unsigned integer type and the ABS flag is not set.
	ErrorSignedToUnsigned = internal.ErrorSignedToUnsigned

	// ErrorInvalidOption is a format string (not an error value) used to build
	// error messages when an Op flag carries an unexpected value type.
	ErrorInvalidOption = internal.ErrorInvalidOption

	// ErrorStrErrorCastingFunc is a format string (not an error value) used
	// when an element cast fails inside a Func[T] closure generator.
	ErrorStrErrorCastingFunc = internal.ErrorStrErrorCastingFunc

	// ErrorStrUnableToCast is a format string (not an error value) used when
	// a value cannot be converted to the requested target type.
	ErrorStrUnableToCast = internal.ErrorStrUnableToCast

	// Error is a deprecated alias for [ErrorUnableToCast].
	//
	// Deprecated: use [ErrorUnableToCast].
	Error = ErrorUnableToCast
)

Sentinel errors and reusable format strings used throughout the package. These are re-exports of the values defined in the internal package so that callers see them through the cast namespace while the conversion code lives behind the internal/ boundary.

Functions

func To

func To[TTo Types](v any, o ...Op) TTo

To casts the value v to the given type, ignoring any errors. See the ToE documentation for more information.

Example (BigFloat)
f := cast.To[*big.Float]("3.14")
fmt.Printf("%v", f.Text('f', 2))
Output:
3.14
Example (BigInt)
n := cast.To[*big.Int]("123456789012345678901234567890")
fmt.Printf("%v", n)
Output:
123456789012345678901234567890
Example (BigIntHex)
// Base is auto-detected: 0x=hex, 0o=octal, 0b=binary, else decimal.
n := cast.To[*big.Int]("0xff")
fmt.Printf("%v", n)
Output:
255
Example (Bool)
fmt.Println(cast.To[bool](1))
fmt.Println(cast.To[bool](0))
Output:
true
false
Example (Chan)
ch := cast.To[chan int]("10")
v := <-ch
fmt.Printf("%v (%T)", v, v)
Output:
10 (int)
Example (ChanLength)
ch := cast.To[chan int](10, cast.Op{cast.LENGTH, 5})
v := <-ch
fmt.Printf("%v (cap %d)", v, cap(ch))
Output:
10 (cap 5)
Example (ChanSlice)
ch := cast.To[chan []int]([]string{"1", "2", "3"})
fmt.Printf("%v (%T)", <-ch, ch)
Output:
[1 2 3] (chan []int)
Example (Complex128)
v := cast.To[complex128](3.14)
fmt.Printf("%v", v)
Output:
(3.14+0i)
Example (Complex64)
v := cast.To[complex64](float32(1.5))
fmt.Printf("%v", v)
Output:
(1.5+0i)
Example (DecodeScalar)
// DECODE=json unwraps a JSON-encoded string before converting.
v := cast.To[int](`"42"`, cast.Op{cast.DECODE, "json"})
fmt.Printf("%v", v)
Output:
42
Example (DecodeSlice)
// DECODE=json forces JSON decoding for a slice target.
v := cast.To[[]int](`[1,2,3]`, cast.Op{cast.DECODE, "json"})
fmt.Printf("%v", v)
Output:
[1 2 3]
Example (Duration)
d := cast.To[time.Duration]("1h30m")
fmt.Printf("%v", d)
Output:
1h30m0s
Example (DurationFromInt)
// int64 input is nanoseconds.
d := cast.To[time.Duration](int64(5_000_000_000))
fmt.Printf("%v", d)
Output:
5s
Example (ErrorTarget)
err := fmt.Errorf("something failed")
result := cast.To[error](err)
fmt.Printf("%v", result)
Output:
something failed
Example (Float64)
v := cast.To[float64]("1.234")
fmt.Printf("%#v (%T)", v, v)
Output:
1.234 (float64)
Example (Func)
f := cast.To[cast.Func[int]]("10")
fmt.Printf("%v (%T)", f(), f())
Output:
10 (int)
Example (FuncChan)
f := cast.To[cast.Func[chan int]](42)
fmt.Printf("%v", <-f())
Output:
42
Example (Int)
v := cast.To[int]("1")
fmt.Printf("%#v (%T)", v, v)
Output:
1 (int)
Example (Map)
m := cast.To[map[string]int](map[string]string{"a": "1", "b": "2"})
fmt.Printf("a=%v b=%v (%T)", m["a"], m["b"], m)
Output:
a=1 b=2 (map[string]int)
Example (MapFromJSONString)
m := cast.To[map[string]int](`{"a":1,"b":2}`)
fmt.Printf("a=%v b=%v", m["a"], m["b"])
Output:
a=1 b=2
Example (MapFromMap)
m := cast.To[map[string]int](map[string]string{"a": "1"})
fmt.Printf("%v (%T)", m["a"], m["a"])
Output:
1 (int)
Example (MapFromPrivateStruct)
// PRIVATE includes unexported fields as map keys.
type Point struct{ x, y int }
m := cast.To[map[string]any](Point{x: 3, y: 4}, cast.Op{cast.PRIVATE, true})
fmt.Printf("x=%v y=%v", m["x"], m["y"])
Output:
x=3 y=4
Example (MapFromSlice)
m := cast.To[map[int]string]([]string{"a", "b", "c"})
fmt.Printf("%v (%T)", m[0], m[0])
Output:
a (string)
Example (MapFromStruct)
type Point struct{ X, Y int }
m := cast.To[map[string]any](Point{X: 3, Y: 4})
fmt.Printf("X=%v Y=%v", m["X"], m["Y"])
Output:
X=3 Y=4
Example (MapToPrivateStruct)
// PRIVATE allows map values to be written into unexported struct fields.
type Point struct{ x, y int }
p := cast.To[Point](map[string]any{"x": 3, "y": 4}, cast.Op{cast.PRIVATE, true})
fmt.Printf("x=%v y=%v (%T)", p.x, p.y, p)
Output:
x=3 y=4 (cast_test.Point)
Example (MapToStruct)
type MyStruct struct {
	X int
	Y int
	A string
	B string
}
p := cast.To[MyStruct](map[string]string{
	"X": "3", "Y": "4", "A": "hello", "B": "world",
})
fmt.Printf("p=(%T), X=%v (%T), Y=%v (%T), A=%v (%T), B=%v (%T)",
	p, p.X, p.X, p.Y, p.Y, p.A, p.A, p.B, p.B)
Output:
p=(cast_test.MyStruct), X=3 (int), Y=4 (int), A=hello (string), B=world (string)
Example (MapToStructTags)
type MyStruct struct {
	X int    `cast:"field_x"`
	Y int    `cast:"field_y"`
	A string `cast:"field_a"`
	B string `cast:"field_b"`
}
p := cast.To[MyStruct](map[string]string{
	"field_x": "3", "field_y": "4", "field_a": "hello", "field_b": "world",
})
fmt.Printf("p=(%T), X=%v (%T), Y=%v (%T), A=%v (%T), B=%v (%T)",
	p, p.X, p.X, p.Y, p.Y, p.A, p.A, p.B, p.B)
Output:
p=(cast_test.MyStruct), X=3 (int), Y=4 (int), A=hello (string), B=world (string)
Example (NetIP)
ip := cast.To[net.IP]("192.168.1.1")
fmt.Printf("%v", ip)
Output:
192.168.1.1
Example (NetIPFromUint32)
// uint32 encodes a packed big-endian IPv4 address.
ip := cast.To[net.IP](uint32(0xC0A80101))
fmt.Printf("%v", ip)
Output:
192.168.1.1
Example (Regexp)
re := cast.To[*regexp.Regexp](`^\d+$`)
fmt.Printf("%v %v", re.MatchString("42"), re.MatchString("hi"))
Output:
true false
Example (Slice)
v := cast.To[[]int]([]string{"1", "2", "3"})
fmt.Printf("%v (%T)", v, v)
Output:
[1 2 3] ([]int)
Example (SliceUniqueValues)
v := cast.To[[]int]([]int{1, 2, 1, 3}, cast.Op{cast.UNIQUE_VALUES, true})
fmt.Printf("%v (%T)", v, v)
Output:
[1 2 3] ([]int)
Example (String)
v := cast.To[string](1.234)
fmt.Printf("%#v (%T)", v, v)
Output:
"1.234" (string)
Example (StringFromBytes)
v := cast.To[string]([]byte("hello"))
fmt.Printf("%v", v)
Output:
hello
Example (StringJson)
v := cast.To[string](`hello "world"`, cast.Op{cast.JSON, true})
fmt.Printf("%v", v)
Output:
"hello \"world\""
Example (StringerTarget)
// Any source that already implements fmt.Stringer is returned as-is.
ip := net.ParseIP("127.0.0.1")
result := cast.To[fmt.Stringer](ip)
fmt.Printf("%v", result)
Output:
127.0.0.1
Example (Struct)
type Point struct{ X, Y int }
p := cast.To[Point](map[string]any{"X": "3", "Y": "4"})
fmt.Printf("X=%v Y=%v (%T)", p.X, p.Y, p)
Output:
X=3 Y=4 (cast_test.Point)
Example (StructNested)
type Address struct{ City, Country string }
type Person struct {
	Name    string
	Age     int
	Address Address
}
m := map[string]any{
	"Name": "Alice",
	"Age":  "30",
	"Address": map[string]any{
		"City":    "Portland",
		"Country": "US",
	},
}
p := cast.To[Person](m)
fmt.Printf("Name=%v Age=%v City=%v Country=%v", p.Name, p.Age, p.Address.City, p.Address.Country)
Output:
Name=Alice Age=30 City=Portland Country=US
Example (StructToMap)
type YourStruct struct {
	X int
	Y int
	A string
	B string
}
p := cast.To[map[string]string](YourStruct{X: 3, Y: 4, A: "hello", B: "world"})
fmt.Printf("p=(%T), X=%v (%T), Y=%v (%T), A=%v (%T), B=%v (%T)",
	p, p["X"], p["X"], p["Y"], p["Y"], p["A"], p["A"], p["B"], p["B"])
Output:
p=(map[string]string), X=3 (string), Y=4 (string), A=hello (string), B=world (string)
Example (StructToMapNonStrict)
type YourStruct struct {
	X int
	Y int
	A string
	B string
}
// Non-strict: string fields A and B cannot convert to int and silently become 0.
p := cast.To[map[string]int](YourStruct{X: 3, Y: 4, A: "hello", B: "world"})
fmt.Printf("p=(%T), X=%v (%T), Y=%v (%T), A=%v (%T), B=%v (%T)",
	p, p["X"], p["X"], p["Y"], p["Y"], p["A"], p["A"], p["B"], p["B"])
Output:
p=(map[string]int), X=3 (int), Y=4 (int), A=0 (int), B=0 (int)
Example (StructToStruct)
type MyStruct struct {
	X int
	Y int
	A string
	B string
}
type YourStruct struct {
	X string
	Y string
	A string
	B string
}
p := cast.To[MyStruct](YourStruct{X: "3", Y: "4", A: "hello", B: "world"})
fmt.Printf("p=(%T), X=%v (%T), Y=%v (%T), A=%v (%T), B=%v (%T)",
	p, p.X, p.X, p.Y, p.Y, p.A, p.A, p.B, p.B)
Output:
p=(cast_test.MyStruct), X=3 (int), Y=4 (int), A=hello (string), B=world (string)
Example (StructToStructJsonTags)
type MyStruct struct {
	X int    `json:"fieldX"`
	Y int    `json:"fieldY"`
	a string `json:"fieldA"`
	b string `json:"fieldB"`
}
type YourStruct struct {
	fieldX string
	fieldY string
	fieldA string
	fieldB string
}
p := cast.To[MyStruct](YourStruct{fieldX: "3", fieldY: "4", fieldA: "hello", fieldB: "world"}, cast.Op{cast.PRIVATE, true})
fmt.Printf("p=(%T), X=%v (%T), Y=%v (%T), a=%v (%T), b=%v (%T)",
	p, p.X, p.X, p.Y, p.Y, p.a, p.a, p.b, p.b)
Output:
p=(cast_test.MyStruct), X=3 (int), Y=4 (int), a=hello (string), b=world (string)
Example (StructToStructPrivate)
type MyStruct struct {
	X int
	Y int
	a string
	b string
}
type YourStruct struct {
	X string
	Y string
	a string
	b string
}
p := cast.To[MyStruct](YourStruct{X: "3", Y: "4", a: "hello", b: "world"}, cast.Op{cast.PRIVATE, true})
fmt.Printf("p=(%T), X=%v (%T), Y=%v (%T), a=%v (%T), b=%v (%T)",
	p, p.X, p.X, p.Y, p.Y, p.a, p.a, p.b, p.b)
Output:
p=(cast_test.MyStruct), X=3 (int), Y=4 (int), a=hello (string), b=world (string)
Example (Time)
t := cast.To[time.Time]("2024-04-22T12:00:00Z")
fmt.Printf("%v", t.Format(time.RFC3339))
Output:
2024-04-22T12:00:00Z
Example (TimeFormat)
// FORMAT overrides the default set of tried formats.
t := cast.To[time.Time]("2024/04/22", cast.Op{cast.FORMAT, "2006/01/02"})
fmt.Printf("%v", t.Format(time.DateOnly))
Output:
2024-04-22
Example (TimeFromFloat)
// float64 input is Unix seconds; fractional seconds are preserved.
t := cast.To[time.Time](float64(1.5))
fmt.Printf("%v", t.Format(time.RFC3339Nano))
Output:
1970-01-01T00:00:01.5Z
Example (TimeFromInt)
// int64 input is Unix nanoseconds.
t := cast.To[time.Time](int64(1_000_000_000))
fmt.Printf("%v", t.Format(time.RFC3339))
Output:
1970-01-01T00:00:01Z
Example (UintAbs)
v := cast.To[uint]("-1", cast.Op{cast.ABS, true})
fmt.Printf("%v (%T)", v, v)
Output:
1 (uint)
Example (Url)
u := cast.To[*url.URL]("https://example.com/path?q=1")
fmt.Printf("%v %v", u.Host, u.Path)
Output:
example.com /path

func ToE

func ToE[TTo Types](val any, ops ...Op) (panicTo TTo, panicErr error)

ToE casts the value v to the given type, returning any errors.

ops is an optional variadic list of Op values that control conversion behavior. If omitted, the default conversion behavior for the target type is used. Available options depend on the target type; see the documentation for the specific type conversion function for more information.

Complex types have specific default behaviors, for example:

  • If the target type is a channel, a buffered channel of size 1 is created and the cast value `v` is sent to the channel before it is returned.

  • If the target type is a slice, a slice is created. To pre-allocate backing capacity set the LENGTH flag: `cast.ToE[[]int](v, cast.Op{cast.LENGTH, 10})`. The source must itself be a slice or array; scalar sources are rejected.

  • If the target type is a map, the source is converted into the target map type. Supported sources: map (key/value types cast), struct or *struct (field names become keys), slice or array (indices become keys).

See the documentation for the specific type conversion function for more information.

Example (BigFloat)
_, e := cast.ToE[*big.Float]("not-a-float")
fmt.Printf("err=%v", e != nil)
Output:
err=true
Example (BigInt)
_, e := cast.ToE[*big.Int]("not-a-number")
fmt.Printf("err=%v", e != nil)
Output:
err=true
Example (BoolErr)
_, e := cast.ToE[bool]("maybe")
fmt.Printf("err=%v", e != nil)
Output:
err=true
Example (ChanErr)
_, e := cast.ToE[chan int]("not-a-number")
fmt.Printf("err=%v", e != nil)
Output:
err=true
Example (Complex128)
_, e := cast.ToE[complex128]("not-a-number")
fmt.Printf("err=%v", e != nil)
Output:
err=true
Example (DecodeErr)
// DECODE=json with invalid JSON returns an error.
_, e := cast.ToE[[]int]("not json", cast.Op{cast.DECODE, "json"})
fmt.Printf("err=%v", e != nil)
Output:
err=true
Example (Duration)
// A bare number without a unit suffix is not a valid duration string.
_, e := cast.ToE[time.Duration]("5")
fmt.Printf("err=%v", e != nil)
Output:
err=true
Example (ErrorTarget)
// A source that does not implement error always fails.
_, e := cast.ToE[error](42)
fmt.Printf("err=%v", e != nil)
Output:
err=true
Example (ErrorWithDefault)
v, e := cast.ToE[int]("Hi!", cast.Op{cast.DEFAULT, 10})
fmt.Printf("%#v (%T), %v", v, v, e)
Output:
10 (int), strconv.ParseFloat: parsing "Hi!": invalid syntax: strconv.ParseFloat: parsing "Hi!": invalid syntax: unable to cast "Hi!" of type string to int
Example (Float64)
_, e := cast.ToE[float64]("not-a-float")
fmt.Printf("err=%v", e != nil)
Output:
err=true
Example (FuncErr)
_, e := cast.ToE[cast.Func[int]]("not-a-number")
fmt.Printf("err=%v", e != nil)
Output:
err=true
Example (Int)
_, e := cast.ToE[int]("not-a-number")
fmt.Printf("err=%v", e != nil)
Output:
err=true
Example (MapDuplicateKeyError)
// After casting, "1" and "01" both become the integer key 1 — a duplicate.
m, e := cast.ToE[map[int]string](
	map[string]string{"1": "one", "01": "also-one"},
	cast.Op{cast.DUPLICATE_KEY_ERROR, true},
)
fmt.Printf("m=%v, err=%v", m, e != nil)
Output:
m=map[], err=true
Example (MapErr)
// A scalar source cannot be converted to a map.
_, e := cast.ToE[map[string]int](42)
fmt.Printf("err=%v", e != nil)
Output:
err=true
Example (NetIP)
_, e := cast.ToE[net.IP]("not-an-ip")
fmt.Printf("err=%v", e != nil)
Output:
err=true
Example (Regexp)
_, e := cast.ToE[*regexp.Regexp]("[unclosed")
fmt.Printf("err=%v", e != nil)
Output:
err=true
Example (SliceErr)
// Elements that cannot convert to the target type cause an error.
_, e := cast.ToE[[]int]([]string{"a", "b"})
fmt.Printf("err=%v", e != nil)
Output:
err=true
Example (String)
// A map containing a channel cannot be JSON-marshalled — string conversion fails.
_, e := cast.ToE[string](map[string]chan int{"a": make(chan int)})
fmt.Printf("err=%v", e != nil)
Output:
err=true
Example (StringerTarget)
// A source that does not implement fmt.Stringer always fails.
_, e := cast.ToE[fmt.Stringer](42)
fmt.Printf("err=%v", e != nil)
Output:
err=true
Example (StructStrict)
type Point struct{ X, Y int }
// "Z" has no matching field in Point — STRICT turns that into an error.
_, e := cast.ToE[Point](
	map[string]any{"X": 1, "Y": 2, "Z": 3},
	cast.Op{cast.STRICT, true},
)
fmt.Printf("err=%v", e != nil)
Output:
err=true
Example (Time)
_, e := cast.ToE[time.Time]("not-a-time")
fmt.Printf("err=%v", e != nil)
Output:
err=true
Example (TimeFormat)
// With FORMAT set, standard formats are not tried as a fallback.
// "2024-04-22" uses dashes but the custom format expects slashes.
_, e := cast.ToE[time.Time]("2024-04-22", cast.Op{cast.FORMAT, "2006/01/02"})
fmt.Printf("err=%v", e != nil)
Output:
err=true
Example (UintErr)
v, e := cast.ToE[uint]("-1")
fmt.Printf("%v (%T), %v", v, v, e)
Output:
0 (uint), cannot cast signed value to unsigned integer: unable to cast "-1" of type string to uint
Example (Url)
// nil is the simplest source that always errors for *url.URL.
_, e := cast.ToE[*url.URL](nil)
fmt.Printf("err=%v", e != nil)
Output:
err=true

Types

type Flag added in v2.0.1

type Flag = internal.Flag

Flag is the key type for conversion options passed to To and ToE.

type Func

type Func[TTo Types] func() TTo

Func is a named zero-argument function type that returns a T. A named type is required because Go generics cannot use plain function literals as type parameters directly.

type Op added in v2.0.1

type Op = internal.Op

Op is a single key/value option passed to To or ToE. Build one with a Flag constant and the appropriate value type for that flag.

The Val type must exactly match the target type T for DEFAULT, or the converter returns an error immediately — before the input is even inspected.

type Tbase

type Tbase interface {
	~int | ~int8 | ~int16 | ~int32 | ~int64 |
		~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
		~float32 | ~float64 |
		~complex64 | ~complex128 |
		~string | ~bool |
		any
}

Tbase covers all scalar types. The any term makes this constraint effectively unconstrained — all types satisfy it. This is intentional: interface targets like error and fmt.Stringer need to be expressible as TTo, and there is no way to enumerate all interface types. Unsupported kinds are rejected at runtime by ToE's dispatch switch.

type Tchan

type Tchan interface {
	~chan Tbase |
		~chan []int | ~chan []int8 | ~chan []int16 | ~chan []int32 | ~chan []int64 |
		~chan []uint | ~chan []uint8 | ~chan []uint16 | ~chan []uint32 | ~chan []uint64 | ~chan []uintptr |
		~chan []float32 | ~chan []float64 |
		~chan []complex64 | ~chan []complex128 |
		~chan []string | ~chan []bool |
		~chan []any | ~chan Func[Tbase] |
		~chan chan Tbase
}

Tchan covers channels of scalars (~chan Tbase covers all basic-type channels in one term), channels of slices, channels of Func values, and nested channels (chan chan T).

type Tmap

type Tmap interface {
	~map[Tbase]Tbase |
		~map[Tbase][]int |
		~map[Tbase][]int8 |
		~map[Tbase][]int16 |
		~map[Tbase][]int32 |
		~map[Tbase][]int64 |
		~map[Tbase][]uint |
		~map[Tbase][]uint8 |
		~map[Tbase][]uint16 |
		~map[Tbase][]uint32 |
		~map[Tbase][]uint64 |
		~map[Tbase][]uintptr |
		~map[Tbase][]float32 |
		~map[Tbase][]float64 |
		~map[Tbase][]complex64 |
		~map[Tbase][]complex128 |
		~map[Tbase][]string |
		~map[Tbase][]bool |
		~map[Tbase][]any |
		~map[Tbase][]Func[Tbase]
}

Tmap covers map types whose keys are any Tbase type and whose values are either a scalar Tbase or a slice of scalars. Named types with a matching underlying map type (e.g. type Attrs map[string]any) also satisfy Tmap.

type Tslice

type Tslice interface {
	~[]int | ~[]int8 | ~[]int16 | ~[]int32 | ~[]int64 |
		~[]uint | ~[]uint8 | ~[]uint16 | ~[]uint32 | ~[]uint64 | ~[]uintptr |
		~[]float32 | ~[]float64 |
		~[]complex64 | ~[]complex128 |
		~[]string | ~[]bool |
		~[]any
}

Tslice covers slice types of every scalar element kind, plus named types with the same underlying slice type (e.g. type Tags []string).

type Types

type Types interface {
	Tbase | Tslice | Tchan | Tmap | Func[Tbase] |
		Func[[]int] | Func[[]int8] | Func[[]int16] | Func[[]int32] | Func[[]int64] |
		Func[[]uint] | Func[[]uint8] | Func[[]uint16] | Func[[]uint32] | Func[[]uint64] | Func[[]uintptr] |
		Func[[]float32] | Func[[]float64] |
		Func[[]complex64] | Func[[]complex128] |
		Func[[]string] | Func[[]bool] | Func[[]any] |
		Func[chan int] | Func[chan int8] | Func[chan int16] | Func[chan int32] | Func[chan int64] |
		Func[chan uint] | Func[chan uint8] | Func[chan uint16] | Func[chan uint32] | Func[chan uint64] | Func[chan uintptr] |
		Func[chan float32] | Func[chan float64] |
		Func[chan complex64] | Func[chan complex128] |
		Func[chan string] | Func[chan bool] | Func[chan any]
}

Types is the top-level constraint that To and ToE accept as TTo. It unions all supported target categories. Func variants for slices and channels are enumerated explicitly because Go does not expand Func[Tslice] into all individual Func[[]T] terms automatically.

Directories

Path Synopsis
internal
cast
Package cast (internal) contains the private implementation of the cast package.
Package cast (internal) contains the private implementation of the cast package.