cast

package module
v0.0.0-...-cd84ca7 Latest Latest
Warning

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

Go to latest
Published: Jan 1, 2025 License: MIT Imports: 5 Imported by: 13

README

go-cast

Package cast provides tools for safely converting from one type to another, without information loss, for the Go programming language.

Documention

Online documentation, which includes examples, can be found at: http://godoc.org/github.com/reiver/go-cast

GoDoc

Example

For an example, let's look at converting to an int64.

You can safely convert a uint8, uint16, uint32, plus an int, int8, int16, int32, int64, into an int64 without information loss.

In other words, if v (in the following example code) is any of the types in the list just mentioned, then the following code would successfully return an int64 of the same numeric value.

i64, err := cast.Int64(v)

More Examples

There is something similar for the other Go built-in types. I.e.,:

b, err := cast.Bool(v)
c64, err := cast.Complex64(v)
c128, err := cast.Complex128(v)
f32, err := cast.Float32(v)
f64, err := cast.Float64(v)
i, err := cast.Int(v)
i8, err := cast.Int8(v)
i16, err := cast.Int16(v)
i32, err := cast.Int32(v)
i64, err := cast.Int64(v)
s, err := cast.String(v)
t, err := cast.Time(v)
u, err := cast.Uint(v)
u8, err := cast.Uint8(v)
u16, err := cast.Uint16(v)
u32, err := cast.Uint32(v)
u64, err := cast.Uint64(v)

Even More Examples

In addition to supporting those Go built-in types, this package also has tools for casting with common vector types:

// [2]float64
fv2, err := cast.Float64x2(v)
// [3]float64
fv3, err := cast.Float64x3(v)
// [4]float64
fv4, err := cast.Float64x4(v)

Advanced Example

This package also supports converting from custom types, as long as that custom type implement a special method.

For int64, the special method is:

interface {
	Int64() (int64, error)
}

For example:

type Always5 struct{}

func (receiver Always5) Int64() (int64, error) {
	return 5, nil
}

// ...

var v Always5

// ...

i64, err := cast.Int64(v)

More Advanced Example

The other special methods are:

interface {
	Bool() (bool, error)
}
interface {
	 Complex64() (complex64, error)
}
interface {
	 Complex128() (complex128, error)
}
interface {
	 Float32() (float32, error)
}
interface {
	 Float64() (float64, error)
}
interface {
	 Int() (int, error)
}
interface {
	 Int8() (int8, error)
}
interface {
	 Int16() (int16, error)
}
interface {
	 Int32() (int32, error)
}
interface {
	 Int64() (int64, error)
}
interface {
	 String() (String, error)
}
interface {
	 Time() (time.Time, error)
}
interface {
	 Uint() (uint, error)
}
interface {
	 Uint8() (uint8, error)
}
interface {
	 Uint16() (uint16, error)
}
interface {
	 Uint32() (uint32, error)
}
interface {
	 Uint64() (uint64, error)
}

fmt.Stringer

For converting to a Go string, the special method for converting from a custom type is:

interface {
	 String() (String, error)
}

This potentially conflicts with the "fmt" package's fmt.Stringer interface:

package fmt

// ...

type Stringer interface {
	String() string
}

(Because these methods have the same name, a type cannot have both.)

To deal with this, this package will use either of these, when trying to convert from a custom type to a string.

So both "String() (String, error)" and "String() string" are acceptable, to this package, for casting from a custom type to a Go string.

Import

To import package cast use import code like the follownig:

import "github.com/reiver/go-cast"

Installation

To install package cast do the following:

GOPROXY=direct go get https://github.com/reiver/go-cast

Author

Package cast was written by Charles Iliya Krempeaux

Documentation

Overview

Package cast provides tools for safely converting from one type to another, without information loss.

For an example, let's look at converting to an int64.

You can safely convert a uint8, uint16, uint32, plus an int, int8, int16, int32, int64, into an int64 without information loss.

In other words, if `v` (in the following example code) is any of the types in the list just mentioned, then the following code would successfully return an `int64` of the same numeric value.

i64, err := cast.Int64(v)

In addition to these types built into Go (that were in the list), this package also supports converting custom types, as long as they implement a special method.

For int64, the special method is:

interface {
	Int64() (int64, error)
}

For example:

type Always5 struct{}

func (receiver Always5) Int64() (int64, error) {
	return 5, nil
}

// ...

var v Always5

// ...

i64, err := cast.Int64(v)

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Bool

func Bool(v any) (bool, error)

Bool will return a bool when `v` is of type bool, or has a method:

type interface {
	Bool() (bool, error)
}

... that returns successfully.

Else it will return an error.

Example (ConvertFromFalseBool)
v := false

b, err := cast.Bool(v)
if nil != err {
	fmt.Printf("Problem casting to bool: %v \n", err)
	return
}

fmt.Printf("b = %t \n", b)
Output:


b = false
Example (ConvertFromTrueBool)
v := true

b, err := cast.Bool(v)
if nil != err {
	fmt.Printf("Problem casting to bool: %v \n", err)
	return
}

fmt.Printf("b = %t \n", b)
Output:


b = true
Example (CustomTypeFuzzyLogic1)
// type FuzzyLogic struct {
// 	value float64
// }
//
// func (receiver FuzzyLogic) Bool() (bool, error) {
// 	result := receiver.value > 0.5
//
// 	return result, nil
// }
//
// var (
// 	FuzzyLogicFalse = FuzzyLogic{value: 0.0}
// 	FuzzyLogicMaybe = FuzzyLogic{value: 0.5}
// 	FuzzyLogicTrue  = FuzzyLogic{value: 1.0}
// )
v := FuzzyLogicFalse

b, err := cast.Bool(v)
if nil != err {
	fmt.Printf("Problem casting to bool: %v \n", err)
	return
}

fmt.Printf("b = %t\n", b)
Output:


b = false
Example (CustomTypeFuzzyLogic2)
// type FuzzyLogic struct {
// 	value float64
// }
//
// func (receiver FuzzyLogic) Bool() (bool, error) {
// 	result := receiver.value > 0.5
//
// 	return result, nil
// }
//
// var (
// 	FuzzyLogicFalse = FuzzyLogic{value: 0.0}
// 	FuzzyLogicMaybe = FuzzyLogic{value: 0.5}
// 	FuzzyLogicTrue  = FuzzyLogic{value: 1.0}
// )
v := FuzzyLogicTrue

b, err := cast.Bool(v)
if nil != err {
	fmt.Printf("Problem casting to bool: %v \n", err)
	return
}

fmt.Printf("b = %t\n", b)
Output:


b = true

func BoolElse

func BoolElse(v any, alternative bool) bool

BoolElse is similar to Bool except that if a cast cannot be done, it returns the `alternative`.

func Complex128

func Complex128(v any) (complex128, error)

func Complex128Else

func Complex128Else(v any, alternative complex128) complex128

Complex128Else is similar to Complex128 except that if a cast cannot be done, it returns the `alternative`.

func Complex64

func Complex64(v any) (complex64, error)

Complex64 will return a complex64 when `v` is of type complex64, float32, uint8, uint16, int8, int16, or has a method:

type interface {
	Complex64() (complex64, error)
}

Else it will return an error.

When float32, uint8, uint16, int8, int16, are converted to a complex64, their value goes into the "real" component of the complex number.

func Complex64Else

func Complex64Else(v any, alternative complex64) complex64

Complex64Else is similar to Complex64 except that if a cast cannot be done, it returns the `alternative`.

func Float32

func Float32(v any) (float32, error)

Float32 will return an float32 when `v` is of type float32, int16, int8, uint16, uint8 or has a method:

type interface {
	Float32() (float32, error)
}

... that returns successfully, or has a method:

type interface {
	Int16() (int16, error)
}

... that returns successfully, or has a method:

type interface {
	Int8() (int8, error)
}

... that returns successfully, or has a method:

type interface {
	Uint16() (uint16, error)
}

... that returns successfully, or has a method:

type interface {
	Uint8() (uint8, error)
}

... that returns successfully.

Else it will return an error.

func Float32Else

func Float32Else(v any, alternative float32) float32

Float32Else is similar to Float32 except that if a cast cannot be done, it returns the `alternative`.

func Float64

func Float64(v any) (float64, error)

Float64 will return an float64 when `v` is of type float64, float32, int32, int16, int8, uint32, uint16, uint8 or has a method:

type interface {
	Float64() (float64, error)
}

... that returns successfully, or has a method:

type interface {
	Float32() (float32, error)
}

... that returns successfully, or has a method:

type interface {
	Int32() (int32, error)
}

... that returns successfully, or has a method:

type interface {
	Int16() (int16, error)
}

... that returns successfully, or has a method:

type interface {
	Int8() (int8, error)
}

... that returns successfully, or has a method:

type interface {
	Uint32() (uint32, error)
}

... that returns successfully, or has a method:

type interface {
	Uint16() (uint16, error)
}

... that returns successfully, or has a method:

type interface {
	Uint8() (uint8, error)
}

... that returns successfully.

Else it will return an error.

func Float64Else

func Float64Else(v any, alternative float64) float64

Float64Else is similar to Float64 except that if a cast cannot be done, it returns the `alternative`.

func Float64x2

func Float64x2(v any) ([2]float64, error)

func Float64x3

func Float64x3(v any) ([3]float64, error)

func Float64x4

func Float64x4(v any) ([4]float64, error)

func Int

func Int(v any) (int, error)

Int will return an int when `v` is of type int32, int16, int8, int, uint16, uint8 or has a method:

type interface {
        Int32() (int32, error)
}

... that returns successfully, or has a method:

type interface {
        Int16() (int16, error)
}

... that returns successfully, or has a method:

type interface {
        Int8() (int8, error)
}

... that returns successfully, or has a method:

type interface {
        Uint16() (uint16, error)
}

... that returns successfully, or has a method:

type interface {
        Uint8() (uint8, error)
}

... that returns successfully, or has a method:

type interface {
        Uint() (uint, error)
}

... that returns successfully.

Else it will return an error.

func Int16

func Int16(v any) (int16, error)

Int16 will return an int16 when `v` is of type int16, int8, uint8 or has a method:

type interface {
	Int16() (int16, error)
}

... that returns successfully, or has a method:

type interface {
	Int8() (int8, error)
}

... that returns successfully, or has a method:

type interface {
	Uint8() (uint8, error)
}

... that returns successfully.

Else it will return an error.

func Int16Else

func Int16Else(v any, alternative int16) int16

Int16Else is similar to Int16 except that if a cast cannot be done, it returns the `alternative`.

func Int32

func Int32(v any) (int32, error)

Int32 will return an int32 when `v` is of type int32, int16, int8, uint16, uint8 or has a method:

type interface {
	Int32() (int32, error)
}

... that returns successfully, or has a method:

type interface {
	Int16() (int16, error)
}

... that returns successfully, or has a method:

type interface {
	Int8() (int8, error)
}

... that returns successfully, or has a method:

type interface {
	Uint16() (uint16, error)
}

... that returns successfully, or has a method:

type interface {
	Uint8() (uint8, error)
}

... that returns successfully.

Else it will return an error.

func Int32Else

func Int32Else(v any, alternative int32) int32

Int32Else is similar to Int32 except that if a cast cannot be done, it returns the `alternative`.

func Int64

func Int64(v any) (int64, error)

Int64 will return an int64 when `v` is of type int64, int32, int16, int8, int, uint32, uint16, uint8 or has a method:

type interface {
	Int64() (int64, error)
}

... that returns successfully, or has a method:

type interface {
	Int32() (int32, error)
}

... that returns successfully, or has a method:

type interface {
	Int16() (int16, error)
}

... that returns successfully, or has a method:

type interface {
	Int8() (int8, error)
}

... that returns successfully, or has a method:

type interface {
	Int() (int, error)
}

... that returns successfully, or has a method:

type interface {
	Uint32() (uint32, error)
}

... that returns successfully, or has a method:

type interface {
	Uint16() (uint16, error)
}

... that returns successfully, or has a method:

type interface {
	Uint8() (uint8, error)
}

... that returns successfully.

Else it will return an error.

Example (CustomType)
package main

import (
	"fmt"

	"github.com/reiver/go-cast"
)

// Modular3 is an implementation of "mod 3" arithmetic system.
//
// Modular arithmetic systems "wrap around".
//
// You can think of them working like a clock or an odometer digit.
//
// So, with "mod 3" the sequence of numbers is:
// 0, 1, 2, 0, 1, 2, 0, 1, 2, ....
//
// Or, in other words:
//
//	0 + 1 = 1
//
//	1 + 1 = 2
//
//	2 + 1 = 0
//
// For the Modular3 type, adding 1 (i.e., "+ 1") capabilities is provided
// by the Inc method.
type Modular3 struct {
	value uint8
}

// Inc adds 1 (i.e., "+ 1") to a Modular3.
func (receiver *Modular3) Inc() {
	receiver.value = (receiver.value + 1) % 3
}

// String makes Modular3 fit the fmt.Stinger interface,
// so that it will have "nice" output when using it
// with (for example) funcs such as fmt.Printf().
func (receiver Modular3) String() string {
	return fmt.Sprintf("%d₃", receiver.value)
}

// Int64 makes Modular3 work with cast.Int64()
func (receiver Modular3) Int64() (int64, error) {
	u8 := receiver.value % 3

	i64 := int64(u8)

	return i64, nil
}

func main() {

	var x Modular3

	fmt.Printf("x = %v\n", x)
	i64, err := cast.Int64(x)
	if nil != err {
		fmt.Printf("Could not convert to int64, because: %v", err)
		return
	}
	fmt.Printf("i64 = %v\n\n", i64)

	x.Inc()

	fmt.Printf("x = %v\n", x)
	i64, err = cast.Int64(x)
	if nil != err {
		fmt.Printf("Could not convert to int64, because: %v", err)
		return
	}
	fmt.Printf("i64 = %v\n\n", i64)

	x.Inc()

	fmt.Printf("x = %v\n", x)
	i64, err = cast.Int64(x)
	if nil != err {
		fmt.Printf("Could not convert to int64, because: %v", err)
		return
	}
	fmt.Printf("i64 = %v\n\n", i64)

	x.Inc()

	fmt.Printf("x = %v\n", x)
	i64, err = cast.Int64(x)
	if nil != err {
		fmt.Printf("Could not convert to int64, because: %v", err)
		return
	}
	fmt.Printf("i64 = %v\n\n", i64)

	x.Inc()

	fmt.Printf("x = %v\n", x)
	i64, err = cast.Int64(x)
	if nil != err {
		fmt.Printf("Could not convert to int64, because: %v", err)
		return
	}
	fmt.Printf("i64 = %v\n\n", i64)

}
Output:

x = 0₃
i64 = 0

x = 1₃
i64 = 1

x = 2₃
i64 = 2

x = 0₃
i64 = 0

x = 1₃
i64 = 1

func Int64Else

func Int64Else(v any, alternative int64) int64

Int64Else is similar to Int64 except that if a cast cannot be done, it returns the `alternative`.

func Int8

func Int8(v any) (int8, error)

Int8 will return an int8 when `v` is of type int8, or has a method:

type interface {
	Int8() (int8, error)
}

... that returns successfully.

Else it will return an error.

func Int8Else

func Int8Else(v any, alternative int8) int8

Int8Else is similar to Int8 except that if a cast cannot be done, it returns the `alternative`.

func IntElse

func IntElse(v any, alternative int) int

IntElse is similar to Int except that if a cast cannot be done, it returns the `alternative`.

func MustBool

func MustBool(v any) bool

MustBool is like Bool, expect panic()s on an error.

func MustComplex128

func MustComplex128(v any) complex128

MustComplex128 is like Complex128, expect panic()s on an error.

func MustComplex64

func MustComplex64(v any) complex64

MustComplex64 is like Complex64, expect panic()s on an error.

func MustFloat32

func MustFloat32(v any) float32

MustFloat32 is like Float32, expect panic()s on an error.

func MustFloat64

func MustFloat64(v any) float64

MustFloat64 is like Float64, expect panic()s on an error.

func MustFloat64x2

func MustFloat64x2(v any) [2]float64

Float64x2 is like Float64x2, expect panic()s on an error.

func MustFloat64x3

func MustFloat64x3(v any) [3]float64

MustFloat64x3 is like Float64x3, expect panic()s on an error.

func MustFloat64x4

func MustFloat64x4(v any) [4]float64

MustFloat64x4 is like Float64x4, expect panic()s on an error.

func MustInt

func MustInt(v any) int

MustInt is like Int, expect panic()s on an error.

func MustInt16

func MustInt16(v any) int16

MustInt16 is like Int16, expect panic()s on an error.

func MustInt32

func MustInt32(v any) int32

MustInt32 is like Int32, expect panic()s on an error.

func MustInt64

func MustInt64(v any) int64

MustInt64 is like Int64, expect panic()s on an error.

func MustInt8

func MustInt8(v any) int8

MustInt8 is like Int8, expect panic()s on an error.

func MustString

func MustString(v any) string

MustString is like String, expect panic()s on an error.

func MustTime

func MustTime(v any) time.Time

MustTime is like Time, expect panic()s on an error.

func MustUint

func MustUint(v any) uint

MustUint is like Uint, expect panic()s on an error.

func MustUint16

func MustUint16(v any) uint16

MustUint16 is like Uint16, expect panic()s on an error.

func MustUint32

func MustUint32(v any) uint32

MustUint32 is like Uint32, expect panic()s on an error.

func MustUint64

func MustUint64(v any) uint64

MustUint64 is like Uint64, expect panic()s on an error.

func MustUint8

func MustUint8(v any) uint8

MustUint8 is like Uint8, expect panic()s on an error.

func SetString

func SetString(dst any, src any) error

SetString uses cast.String() to try to convert `src` into a string, and then (if successful) tries to assign that string to `dst` if `dst` is of type:

*string

*[]byte

*[]rune

... or of a type that fits:

interface {
	SetString(string)
}

... or of a type that fits:

interface {
	SetString(string) error
}

... or of a type that fits:

interface {
	SetString(string) bool
}

... or of a type that fits:

interface {
	Set(string) error
}

(This interface is part of flag.Value.)

... or of a type that fits:

interface {
	Scan(any) error
}

(This interface matches sql.Scanner.)

func String

func String(v any) (string, error)

String converts `v` into a string, if it is of type:

[]byte

rune

[]rune

string

... or of a type that fits:

interface {
	String() (string, error)
}

... or of a type that fits:

interface {
	String() (string, bool)
}

... or of a type that fits:

interface {
	String() string
}

(This final interface matches fmt.Stringer.)

func StringElse

func StringElse(v any, alternative string) string

StringElse is similar to String except that if a cast cannot be done, it returns the `alternative`.

func Time

func Time(v any) (time.Time, error)

func TimeElse

func TimeElse(v any, alternative time.Time) time.Time

TimeElse is similar to Time except that if a cast cannot be done, it returns the `alternative`.

func Uint

func Uint(v any) (uint, error)

Uint will return an int when `v` is of type uint32, uint16, uint8, int or has a method:

type interface {
        Uint32() (uint32, error)
}

... that returns successfully, or has a method:

type interface {
        Uint16() (uint16, error)
}

... that returns successfully, or has a method:

type interface {
        Uint8() (uint8, error)
}

... that returns successfully, or has a method:

type interface {
        Uint() (uint, error)
}

... that returns successfully.

Else it will return an error.

func Uint16

func Uint16(v any) (uint16, error)

Uint16 will return an int16 when `v` is of type uint16, uint8 or has a method:

type interface {
        Uint16() (uint16, error)
}

... that returns successfully, or has a method:

type interface {
        Uint8() (uint8, error)
}

... that returns successfully.

Else it will return an error.

func Uint16Else

func Uint16Else(v any, alternative uint16) uint16

Uint16Else is similar to Uint16 except that if a cast cannot be done, it returns the `alternative`.

func Uint32

func Uint32(v any) (uint32, error)

Uint32 will return an int32 when `v` is of type uint32, uint16, uint8 or has a method:

type interface {
	Uint32() (uint32, error)
}

... that returns successfully, or has a method:

type interface {
	Uint16() (uint16, error)
}

... that returns successfully, or has a method:

type interface {
	Uint8() (uint8, error)
}

... that returns successfully.

Else it will return an error.

func Uint32Else

func Uint32Else(v any, alternative uint32) uint32

Uint32Else is similar to Uint32 except that if a cast cannot be done, it returns the `alternative`.

func Uint64

func Uint64(v any) (uint64, error)

Uint64 will return an int64 when `v` is of type uint64, uint32, uint16, uint8, uint or has a method:

type interface {
	Uint64() (uint64, error)
}

... that returns successfully, or has a method:

type interface {
	Uint32() (uint32, error)
}

... that returns successfully, or has a method:

type interface {
	Uint16() (uint16, error)
}

... that returns successfully, or has a method:

type interface {
	Uint8() (uint8, error)
}

... that returns successfully, or has a method:

type interface {
	Uint() (uint, error)
}

... that returns successfully.

Else it will return an error.

func Uint64Else

func Uint64Else(v any, alternative uint64) uint64

Uint64Else is similar to Uint64 except that if a cast cannot be done, it returns the `alternative`.

func Uint8

func Uint8(v any) (uint8, error)

Uint8 will return an uint8 when `v` is of type uint8, or has a method:

type interface {
	Uint8() (uint8, error)
}

... that returns successfully.

Else it will return an error.

func Uint8Else

func Uint8Else(v any, alternative uint8) uint8

Uint8Else is similar to Uint8 except that if a cast cannot be done, it returns the `alternative`.

func UintElse

func UintElse(v any, alternative uint) uint

UintElse is similar to Uint except that if a cast cannot be done, it returns the `alternative`.

Types

type CannotCastComplainer

type CannotCastComplainer interface {
	error
	CannotCastComplainer()
}

The CannotCastComplainer interface identifies an error due to a situation where converting from one type to another could not be done.

Example:

s, err := cast.String(v)
if nil != err {
	switch {
	case cast.CannotCastComplainer:
		//@TODO
	default:
		//@TODO
	}
}

type CannotSetComplainer

type CannotSetComplainer interface {
	error
	CannotSetComplainer()
}

The CannotSetComplainer interface identifies an error due to a situation where setting a value of some particular type cannot happen.

This can likely be thought of some type of bug in the code, due to the destination-type or the source-type being the wrong type.

Example:

err := cast.SetString(v)
if nil != err {
	switch {
	case cast.CannotSetComplainer:
		//@TODO
	case cast.CouldNotSetComplainer:
		//@TODO
	default:
		//@TODO
	}
}

type CouldNotSetComplainer

type CouldNotSetComplainer interface {
	error
	CouldNotSetComplainer()
	Unwrap() error
}

The CouldNotSetComplainer interface identifies an error due to a situation where setting a value of some particular type failed with some type of error.

This can likely be thought of some type of run-time error.

Example:

err := cast.SetString(v)
if nil != err {
	switch {
	case cast.CannotSetComplainer:
		//@TODO
	case cast.CouldNotSetComplainer:
		//@TODO
	default:
		//@TODO
	}
}

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL