types

package
v3.11.0+incompatible Latest Latest
Warning

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

Go to latest
Published: Jul 27, 2017 License: Apache-2.0, Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

This package provides out-of-box conversion service.

Default Conversion Service

You could use "NewDefaultConversionService()" function to construct an default implementation for "ConversionService" and "ConverterRegistry".

convSrv := types.NewDefaultConversionService()

Customized converter

You could use "AddConverter()" method to register a converter between two "reflect.Type"s

r.AddConverter(reflect.TypeOf(v1), reflect.TypeOf(v2), your_converter)

Type of interface

In some cases, you need the "reflect.Type" on a defined interface, you could use common/reflect."TypeOfInterface()" to hold the interface for reflection:

type DoSomething interface {
	Perform(int)
	GetData() string
}
var _t_YourType = oreflect.TypeOfInterface((*DoSomething)(nil))

// Checking if a type implements your interface
if yourType.Implements(_t_YourType) {
}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func DoBinding

func DoBinding(sourceObject interface{}, holder interface{})

Convenient function to perform the binding

sourceObject - The source to be converted
holder - The object implements "Binding" interface

This function would panic if the holder doesn't implement "Binding" interface.

func HasBinding

func HasBinding(holder interface{}) bool

Checks if a object has implemented "Binding" interface

Types

type Binding

type Binding interface {
	// Binds the content of source object into this object
	Bind(sourceObject interface{})
}

Defines the binding interface to convert any object to implementing type

Example
/*
	type MyBox struct {
		Name string
	}
	func (b *MyBox) Bind(source interface{}) {
		switch v := source.(type) {
		case int:
			b.Name = fmt.Sprintf("Name by number: %d", v)
		case string:
			b.Name = fmt.Sprintf("Name by string: %s", v)
		default:
			panic(fmt.Sprintf("Cannot be converted from value of type: %T", source))
		}
	}
*/
box := &MyBox{}

DoBinding(44, box)
fmt.Println(box.Name)
DoBinding("BC-908", box)
fmt.Println(box.Name)
Output:

Name by number: 44
Name by string: BC-908
Example (ConversionService)
convSrv := NewDefaultConversionService()

/*
	type MyBox struct {
		Name string
	}
	func (b *MyBox) Bind(source interface{}) {
		switch v := source.(type) {
		case int:
			b.Name = fmt.Sprintf("Name by number: %d", v)
		case string:
			b.Name = fmt.Sprintf("Name by string: %s", v)
		default:
			panic(fmt.Sprintf("Cannot be converted from value of type: %T", source))
		}
	}
*/

// Gets the function of conversion and target type
convertFunc, targetType := BindingToConverter(func() interface{} {
	return &MyBox{}
})

convSrv.AddConverter(TypeOfInt, targetType, convertFunc)
convSrv.AddConverter(TypeOfString, targetType, convertFunc)

fmt.Println(convSrv.ConvertTo(89, targetType).(*MyBox).Name)
fmt.Println(convSrv.ConvertTo("CP-091", targetType).(*MyBox).Name)
Output:

Name by number: 89
Name by string: CP-091

type ConversionService

type ConversionService interface {
	// Checks whether or not a type can be converted to another one
	CanConvert(sourceType reflect.Type, targetType reflect.Type) bool
	// Convert a variable to target type
	ConvertTo(sourceObject interface{}, targetType reflect.Type) interface{}
}

Main interface provided by convsersion service

Example (CustomiedConverter)
convSrv := NewDefaultConversionService()

// import ot "github.com/Cepave/open-falcon-backend/common/reflect/types"
convSrv.AddConverter(
	TypeOfInt8, TypeOfString,
	func(source interface{}) interface{} {
		return fmt.Sprintf("int8:%d", source)
	},
)

fmt.Printf("%s\n", convSrv.ConvertTo(int8(44), TypeOfString))
Output:

int8:44
Example (Map)
convSrv := NewDefaultConversionService()

sourceMap := map[string]int32{
	"Key1": 88,
	"Key2": 92,
	"Key3": 63,
}
// import ot "github.com/Cepave/open-falcon-backend/common/reflect/types"
targetMap := convSrv.ConvertTo(
	sourceMap,
	reflect.MapOf(
		TypeOfString, TypeOfUint64,
	),
).(map[string]uint64)

fmt.Printf("%d, %d, %d\n", targetMap["Key1"], targetMap["Key2"], targetMap["Key3"])
Output:

88, 92, 63
Example (Slice)
convSrv := NewDefaultConversionService()

// import ot "github.com/Cepave/open-falcon-backend/common/reflect/types"
sourceSlice := []string{"76", "38", "99"}
targetSlice := convSrv.ConvertTo(sourceSlice, STypeOfInt).([]int)

fmt.Printf("%#v\n", targetSlice)
Output:

[]int{76, 38, 99}

type Converter

type Converter func(sourceObject interface{}) interface{}

General conversion function

func BindingToConverter

func BindingToConverter(holderBuilder func() interface{}) (Converter, reflect.Type)

Converts the Binding(with builder) to "Converter"

type ConverterRegistry

type ConverterRegistry interface {
	// Adds a customized converter
	AddConverter(sourceType reflect.Type, targetType reflect.Type, converter Converter)
}

Defines the registry for managing converters

type DefaultConversionService

type DefaultConversionService struct {
	// contains filtered or unexported fields
}

Default implementation for conversion service

Abstract

There are two phases for conversion process:

1 - Use converters added by "AddConverter()" method(customized converters).
2 - Use build-in converters if nothing is matched on customized converters.

Build-in converters

If target type is pointer, the converted object would be allocated by new().

If the target type is string, this service would use:

anyValue -> fmt.Sprintf("%v", anyValue)

If source type is string, following target type could be converted:

Int, Uint. Float and Bool

For any non-complex value(which is not array, slice, or channel), the value could be converted to:

Array: Puts the converted element to "[n]string { convertedV }"
type -> [1]type

Slice: Puts the converted element to "[]string { convertedV }". len(slice) == 1. cap(slice) == 1
type -> []type

Channel: Send the converted element to "new(chan string, 1)"
type -> chan type len() == 1

From array to slice(convertible element type)

[3]type -> []type(len == 3, cap == 3)

From array/slice to channel(convertible element type)

[3]type -> Puts every element in array to new(chan type, 3)
[]type { "v1", "v2" } -> Puts len([]type) elements to new(chan type, len([]type))

From channel to slice(convertible element type), this service would try to receive an element from channel(without blocking)

chan type -> []type
chan type -> [n]type

WARNING: The value of channel would be put back.

If the target type is array and the len(source) > len(array), this service would **panic**.

// Panic
[]type { v1, v2 } -> [1]type

From a map to another map of different types: Both of the key and value of maps must be convertible

map[string]int -> map[int]string

The key of map, must obey the rules defined by go lang:

The comparison operators == and != must be fully defined for operands of the key type;
thus the key type must not be a function, map, or slice.
If the key type is an interface type,
these comparison operators must be defined for the dynamic key values;
failure will cause a run-time panic.

See map type: https://golang.org/ref/spec#Map_types

See comparison operator: https://golang.org/ref/spec#Comparison_operators

Otherwise, see https://golang.org/ref/spec#Conversions

Example
convSrv := NewDefaultConversionService()

stringV := convSrv.ConvertTo(45, TypeOfString)
fmt.Printf("%T:%s\n", stringV, stringV)
Output:

string:45

func NewDefaultConversionService

func NewDefaultConversionService() *DefaultConversionService

Constructs a new instance of default implementation

func (*DefaultConversionService) AddConverter

func (s *DefaultConversionService) AddConverter(sourceType reflect.Type, targetType reflect.Type, converter Converter)

Implements the interface "ConverterRegistry"

func (*DefaultConversionService) CanConvert

func (s *DefaultConversionService) CanConvert(sourceType reflect.Type, targetType reflect.Type) bool

Implements the interface "ConversionService"

Only checks added converters(without processing of pointer)

func (*DefaultConversionService) ConvertTo

func (s *DefaultConversionService) ConvertTo(sourceObject interface{}, targetType reflect.Type) interface{}

Implements the interface "ConversionService"

type FormattedConversionService

type FormattedConversionService interface {
	ConversionService

	// Generates the string-representation of an object
	Print(sourceObject interface{}) string
	// Generates the string-representation of an object(with locale)
	PrintWithLocale(sourceObject interface{}, locale *time.Location) string

	// Converts the string value to target value
	Scan(stringValue string) interface{}
	// Converts the string value to target value(with locale)
	ScanWithLocale(stringValue string, locale *time.Location) interface{}
}

Sub-type of ConversionService, which provides methods of "Print()" and "Scan()"...

type Formatter

type Formatter interface {
	Parser
	Printer
}

Combines Parser and Printer interface

type FormatterRegistry

type FormatterRegistry interface {
	ConverterRegistry

	// Adds formatter with type of object
	AddFormatter(objectType reflect.Type, formatter Formatter)
	// Adds formatter by type of struct's field
	AddFormatterForField(field reflect.StructField, formatter Formatter)
}

Sub-type of ConverterRegistry, with registering of formatter.

type Parser

type Parser interface {
	Scan(stringValue string, locale *time.Location) interface{}
}

Defines the parsing of a string value(with locale) to desired value

type Printer

type Printer interface {
	Print(object interface{}, locale *time.Location) string
}

Defines the string-representation of a value to string value(with locale)

Jump to

Keyboard shortcuts

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