https://github.com/ctx42/convert
Go 32bit and 64bit safe conversions between types.
https://github.com/ctx42/convert
go golang golang-library security
Last synced: 6 months ago
JSON representation
Go 32bit and 64bit safe conversions between types.
- Host: GitHub
- URL: https://github.com/ctx42/convert
- Owner: ctx42
- License: mit
- Created: 2025-12-12T12:18:09.000Z (7 months ago)
- Default Branch: master
- Last Pushed: 2026-01-02T12:40:25.000Z (6 months ago)
- Last Synced: 2026-01-08T15:46:44.829Z (6 months ago)
- Topics: go, golang, golang-library, security
- Language: Go
- Homepage: https://blog.ctx42.com
- Size: 219 KB
- Stars: 1
- Watchers: 0
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.md
Awesome Lists containing this project
README
[](https://goreportcard.com/report/github.com/ctx42/convert)
[](https://pkg.go.dev/github.com/ctx42/convert)

* [Installation](#installation)
* [Converters](#converters)
* [Converter Registry](#converter-registry)
* [Converter Types](#converter-types)
* [AnyToXXX Converters.](#anytoxxx-converters)
* [Register Custom Converters](#register-custom-converters)
* [Customize Converters](#customize-converters)
* [32bit vs. 64bit Systems](#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`:
```bash
go get github.com/ctx42/convert
```
## Converters
Use converter functions directly.
```go
// 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:
// 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:
- `uint`
- `uint8`
- `uint16`
- `uint32`
- `uint64`
- `int`
- `int8`
- `int16`
- `int32`
- `int64`
- `float32`
- `float64`
- `byte`
- `rune`
- `uintqptr`
- `time.Duration`
As well as converters implemented only between specific type pairs:
- `convert.StringToDuration`
- `convert.StringToString`
- `convert.StringToTime` - string must be in `time.RFC3339Nano` format.
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.
```go
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:
```
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.
```go
// 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.
```go
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
```
## AnyToXXX Converters.
Module also provides a set of functions which can convert `any` type to a given
type:
- `AnyToByte`
- `AnyToDuration`
- `AnyToFloat32`
- `AnyToFloat64`
- `AnyToInt`
- `AnyToInt8`
- `AnyToInt16`
- `AnyToInt32`
- `AnyToInt64`
- `AnyToUint`
- `AnyToUint8`
- `AnyToUint16`
- `AnyToUint32`
- `AnyToUint64`
- `AnyToUintptr`
- `AnyToRune`
## Register Custom Converters
```go
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:
```
## 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.
```go
// 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:
```
## 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](pkg/convert) directory with
`_32bit` and `_64bit` strings in their filenames.