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 ¶
- To (Chan)
- To (Float64)
- To (Func)
- To (Int)
- To (Slice)
- To (String)
- ToE (Chan_length)
- ToE (Error_with_default)
- ToE (Float64)
- ToE (Int)
- ToE (Map_from_map)
- ToE (Map_from_private_struct)
- ToE (Map_from_slice)
- ToE (Map_from_struct)
- ToE (Map_to_struct)
- ToE (Map_to_struct_tags)
- ToE (Slice_unique_values)
- ToE (String)
- ToE (String_json)
- ToE (Struct_to_map)
- ToE (Struct_to_map_error)
- ToE (Struct_to_struct)
- ToE (Struct_to_struct_json_tags)
- ToE (Struct_to_struct_private)
- ToE (Uint_abs)
- ToE (Uint_err)
Constants ¶
This section is empty.
Variables ¶
var ( Error = fmt.Errorf("unable to cast value") ErrorSignedToUnsigned = fmt.Errorf("cannot cast signed value to unsigned integer") ErrorInvalidOption = "invalid %s value '%v'" ErrorStrErrorCastingFunc = "error casting %T to %T during function generation" ErrorStrUnableToCast = "unable to cast %#.10v of type %T to %T" )
Sentinel errors and reusable format strings used throughout the package.
Functions ¶
func To ¶
To casts the value v to the given type, ignoring any errors. See the ToE documentation more information.
Example (Chan) ¶
ch := cast.To[chan int]("10")
v := <-ch
fmt.Printf("%v (%T)", v, v)
Output: 10 (int)
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 (Int) ¶
v := cast.To[int]("1")
fmt.Printf("%#v (%T)", v, v)
Output: 1 (int)
Example (Slice) ¶
v := cast.To[[]int]([]string{"1", "2", "3"})
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)
func ToE ¶
ToE casts the value v to the given type, returning any errors.
ops (Ops) is an optional parameter providing flags that can be used to modify the default type conversion behavior. If ops is not provided, the default conversion behavior for a given 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 channel with a buffer of 1 is created and the cast value `v` is added to the 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 (Chan_length) ¶
ch, e := cast.ToE[chan int](10, cast.Op{cast.LENGTH, 5})
v := <-ch
fmt.Printf("%v (cap %d), %v", v, cap(ch), e)
Output: 10 (cap 5), <nil>
Example (Error_with_default) ¶
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) ¶
v, e := cast.ToE[float64]("1")
fmt.Printf("%#v (%T), %v", v, v, e)
Output: 1 (float64), <nil>
Example (Int) ¶
v, e := cast.ToE[int]("1")
fmt.Printf("%#v (%T), %v", v, v, e)
Output: 1 (int), <nil>
Example (Map_from_map) ¶
m, e := cast.ToE[map[string]int](map[string]string{"a": "1"})
fmt.Printf("%v (%T), %v", m["a"], m["a"], e)
Output: 1 (int), <nil>
Example (Map_from_private_struct) ¶
type Point struct{ x, y int }
m, e := cast.ToE[map[string]any](Point{x: 3, y: 4}, cast.Op{cast.PRIVATE, true})
fmt.Printf("x=%v y=%v, %v", m["x"], m["y"], e)
Output: x=3 y=4, <nil>
Example (Map_from_slice) ¶
m, e := cast.ToE[map[int]string]([]string{"a", "b", "c"})
fmt.Printf("%v (%T), %v", m[0], m[0], e)
Output: a (string), <nil>
Example (Map_from_struct) ¶
type Point struct{ X, Y int }
m, e := cast.ToE[map[string]any](Point{X: 3, Y: 4})
fmt.Printf("X=%v Y=%v, %v", m["X"], m["Y"], e)
Output: X=3 Y=4, <nil>
Example (Map_to_struct) ¶
type MyStruct struct {
X int
Y int
A string
B string
}
yourData := map[string]string{
"X": "3",
"Y": "4",
"A": "hello",
"B": "world",
}
p, e := cast.ToE[MyStruct](yourData)
fmt.Printf(
"p=(%T), X=%v (%T), Y=%v (%T), A=%v (%T), B=%v (%T), %v",
p, p.X, p.X, p.Y, p.Y, p.A, p.A, p.B, p.B, e,
)
Output: p=(cast_test.MyStruct), X=3 (int), Y=4 (int), A=hello (string), B=world (string), <nil>
Example (Slice_unique_values) ¶
v, e := cast.ToE[[]int]([]int{1, 2, 1, 3}, cast.Op{cast.UNIQUE_VALUES, true})
fmt.Printf("%v (%T), %v", v, v, e)
Output: [1 2 3] ([]int), <nil>
Example (String) ¶
v, e := cast.ToE[string](float64(1.0))
fmt.Printf("%#v (%T), %v", v, v, e)
Output: "1" (string), <nil>
Example (String_json) ¶
v, e := cast.ToE[string](`hello "world"`, cast.Op{cast.JSON, true})
fmt.Printf("%v, %v", v, e)
Output: "hello \"world\"", <nil>
Example (Struct_to_map) ¶
type YourStruct struct {
X int
Y int
A string
B string
}
yourStruct := YourStruct{
X: 3,
Y: 4,
A: "hello",
B: "world",
}
p, e := cast.ToE[map[string]string](yourStruct)
fmt.Printf(
"p=(%T), X=%v (%T), Y=%v (%T), A=%v (%T), B=%v (%T), %v",
p, p["X"], p["X"], p["Y"], p["Y"], p["A"], p["A"], p["B"], p["B"], e,
)
Output: p=(map[string]string), X=3 (string), Y=4 (string), A=hello (string), B=world (string), <nil>
Example (Struct_to_map_error) ¶
type YourStruct struct {
X int
Y int
A string
B string
}
yourStruct := YourStruct{
X: 3,
Y: 4,
A: "hello",
B: "world",
}
p, e := cast.ToE[map[string]int](yourStruct)
fmt.Printf(
"p=(%T), X=%v (%T), Y=%v (%T), A=%v (%T), B=%v (%T), %v",
p, p["X"], p["X"], p["Y"], p["Y"], p["A"], p["A"], p["B"], p["B"], e,
)
Output: p=(map[string]int), X=3 (int), Y=4 (int), A=0 (int), B=0 (int), <nil>
Example (Struct_to_struct) ¶
type MyStruct struct {
X int
Y int
A string
B string
}
type YourStruct struct {
X string
Y string
A string
B string
}
yourStruct := YourStruct{
X: "3",
Y: "4",
A: "hello",
B: "world",
}
p, e := cast.ToE[MyStruct](yourStruct, cast.Op{cast.PRIVATE, true})
fmt.Printf("p=(%T), X=%v (%T), Y=%v (%T), A=%v (%T), B=%v (%T), %v", p, p.X, p.X, p.Y, p.Y, p.A, p.A, p.B, p.B, e)
Output: p=(cast_test.MyStruct), X=3 (int), Y=4 (int), A=hello (string), B=world (string), <nil>
Example (Struct_to_struct_private) ¶
type MyStruct struct {
X int
Y int
a string
b string
}
type YourStruct struct {
X string
Y string
a string
b string
}
yourStruct := YourStruct{
X: "3",
Y: "4",
a: "hello",
b: "world",
}
p, e := cast.ToE[MyStruct](yourStruct, cast.Op{cast.PRIVATE, true})
fmt.Printf("p=(%T), X=%v (%T), Y=%v (%T), a=%v (%T), b=%v (%T), %v", p, p.X, p.X, p.Y, p.Y, p.a, p.a, p.b, p.b, e)
Output: p=(cast_test.MyStruct), X=3 (int), Y=4 (int), a=hello (string), b=world (string), <nil>
Example (Uint_abs) ¶
v, e := cast.ToE[uint]("-1", cast.Op{cast.ABS, true})
fmt.Printf("%v (%T), %v", v, v, e)
Output: 1 (uint), <nil>
Example (Uint_err) ¶
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
func ToStruct ¶ added in v2.1.1
ToStruct casts from into a struct of type T, ignoring errors. See ToStructE for full documentation.
func ToStructE ¶ added in v2.1.1
ToStructE casts from into a struct of type T, returning any errors.
T must be a struct type. The source may be a map with keys convertible to string, or another struct whose field names overlap with T.
Field matching is case-sensitive and tag-aware. The lookup key for each target field is resolved by checking a cast tag first, then a json tag, then the field name. For each target field in T:
- If the source has no matching key, the field retains its zero value (or returns an error when STRICT is set).
- If the source value cannot be cast to the field type, the field is skipped (or returns an error when STRICT is set).
Options:
- DEFAULT: T, value to return on error.
- PRIVATE: bool, include unexported fields in source collection and target hydration.
- STRICT: bool, error on unknown source keys or unconvertible field values.
Types ¶
type Flag ¶ added in v2.0.1
type Flag int
Flag is the key type for conversion options passed to To and ToE.
const ( DEFAULT Flag = iota // TTo, LOCAL — value to return on error; type-specific, not passed to nested casts ABS // bool, GLOBAL — use absolute value during uint conversion DECODE // string, LOCAL — decode string source before conversion; only applies to string/error/Stringer sources; supported values: "JSON"/"json" DUPLICATE_KEY_ERROR // bool, LOCAL — error on duplicate key (map→map only); not meaningful in nested casts FORMAT // string, GLOBAL — Format string for time/duration parsing JSON // bool, GLOBAL — encode strings as JSON LENGTH // int, GLOBAL — initial capacity for slices / buffer size for channels; applies to all slice and chan targets in the tree (slices allow 0; channels require >= 1) PRIVATE // bool, GLOBAL — include unexported struct fields in map output STRICT // bool, GLOBAL — return error instead of skipping unconvertible fields UNIQUE_VALUES // bool, GLOBAL — dedupe slice values; applies to all slice targets in the tree )
Available option flags. Flags fall into two categories:
Global flags propagate through the full conversion tree and are preserved by [ops.Global]. They apply the same way at every level of a nested conversion:
- ABS, JSON, LENGTH, PRIVATE, STRICT, UNIQUE_VALUES
Local flags apply only to the conversion they are passed to and are stripped by [ops.Global]. Container converters read their own local flags, then pass [ops.Global] to element-level casts so the local flags do not leak into nested conversions where they carry no meaning or the wrong type:
- DEFAULT, DUPLICATE_KEY_ERROR
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
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.
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 (struct, pointer, etc.) 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]
}
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.
