README
¶
- Installation
- Converters
- Converter Registry
- Converter Types
- Register Custom Converters
- Customize Converters
- 32bit vs. 64bit Systems
convert is a lightweight Go library for safe type conversions, preventing truncation, overflow, or semantic loss when converting between types.
It has support for 32-bit and 64-bit systems when converting numeric types.
Installation
Install using go get:
go get github.com/ctx42/convert
Converters
Use converter functions directly.
// Successful conversion.
ui8, err := convert.IntToUint8(42)
fmt.Printf("convert.IntToUint8 output: %[1]T(%[1]d) error: %v\n", ui8, err)
// Value too big for uint8.
ui8, err = convert.IntToUint8(420)
fmt.Printf("convert.IntToUint8 output: %[1]T(%[1]d) error: %v\n", ui8, err)
// Unsafe conversion.
f32, err := convert.IntToFloat32(convert.Float32SafeIntMax + 1)
fmt.Printf("convert.IntToUint8 output: %[1]T(%[1]g) error: %v\n", f32, err)
// Output:
// convert.IntToUint8 output: uint8(42) error: <nil>
// convert.IntToUint8 output: uint8(0) error: int value out of range for uint8
// convert.IntToUint8 output: float32(0) error: int value out of safe range for float32
Package convert provides more than 200 converter functions between numeric
types:
uintuint8uint16uint32uint64intint8int16int32int64float32float64byteruneuintqptr
As well as converters implemented only between specific type pairs:
convert.StringToDurationconvert.StringToStringconvert.StringToTime- string must be intime.RFC3339Nanoformat.
All of them pairs are automatically registered in the package-level registry.
Converter Registry
To get a converter function for a pair of types at runtinme use Lookup
function.
cnv := convert.Lookup[int, uint8]()
// Chack cnv is not nil.
have, err := cnv(42)
// Check conversion error.
fmt.Printf("output: %[1]T(%[1]d); error: %v", have, err)
// Output:
// output: uint8(42); error: <nil>
It returns a non-nil converter if the pair has been registered in the package-level registry.
Converter Types
All the converter functions provided by the package match generic FromTo type.
// FromTo represents a converter function that attempts lossless conversion of
// a value from the type "From" to the "To" type. On success, it returns the
// converted value and a nil error. On failure (e.g., truncation, underflow,
// overflow, or semantic loss), it returns the zero value of "To" along with a
// non-nil error describing the issue.
type FromTo[From, To any] func(from From) (to To, err error)
// AnyToAny is a non-generic version of [FromTo]. The behavior is exactly the
// same in terms of error handling.
type AnyToAny func(form any) (to any, err error)
Additionally, package defines non-generic AnyToAny type. Converter functions
can be adapted to it with a helper.
var cnv func(any) (any, error)
cnv = convert.ToAnyAny(convert.Uint8ToUint8)
have, err := cnv("wrong")
fmt.Printf("output: %[1]T(%[1]d); error: %v", have, err)
// Output:
// output: uint8(0); error: invalid type: expected uint8, got string
Register Custom Converters
type A struct{ val int8 }
type B struct{ val int }
// Custom converter function matching [convert.Converter] signature.
my := func(from A) (to B, err error) {
return B{val: int(from.val)}, nil
}
// Register a converter function between types A and B.
old := convert.Register(my)
// If there was already a converter for that source-destination type pair,
// it will be returned, nil otherwise.
_ = old
// Lookup converter registered converter.
cnv := convert.Lookup[A, B]()
// Run conversion.
have, err := cnv(A{42})
fmt.Printf("output: %[1]T(%[1]d); error: %v", have, err)
// Output:
// output: convert_test.B({42}); error: <nil>
Customize Converters
Some converters, like convert.StringToTime, are added to package-level
registry with sane defaults but you can customize them by overwriting the
defeult configuration.
// Register a converter function between types A and B.
def := convert.Register(convert.StringToTime(time.Kitchen))
// The default converter is returned in case you want to restore it.
defer convert.Register(def)
// Lookup converter registered converter.
cnv := convert.Lookup[string, time.Time]()
// Run conversion.
have, err := cnv("4:20AM")
fmt.Printf("output: %s; error: %v", have, err)
// Output:
// output: 0000-01-01 04:20:00 +0000 UTC; error: <nil>
32bit vs. 64bit Systems
In cases where its necessary module implements separate boundary checks for
32-bit and 64-bit systems. See files in convert directory with
_32bit and _64bit strings in their filenames.