mconv

package module
v1.2.1 Latest Latest
Warning

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

Go to latest
Published: Aug 24, 2026 License: MIT Imports: 4 Imported by: 8

README

mconv

Go Report Card codecov Go Reference License Release

中文 | English

mconv 是一个零依赖的 Go 类型转换库,提供基础类型、容器、JSON 和结构体转换。最低支持 Go 1.18。

安装

go get github.com/graingo/mconv

新代码统一导入根包 github.com/graingo/mconvbasiccomplex 子包在 v1 中继续保持兼容,但不作为新的应用代码入口。v2 边界见 V2_MIGRATION.md

快速开始

package main

import (
	"fmt"

	"github.com/graingo/mconv"
)

func main() {
	fmt.Println(mconv.ToString(42))       // 42
	fmt.Println(mconv.ToInt("42"))       // 42
	fmt.Println(mconv.ToBool("yes"))     // true
	fmt.Println(mconv.ToDuration("1m"))  // 1m0s
}

每个宽松入口都有返回错误的 E 版本:

value, err := mconv.ToIntE("42")
if err != nil {
	return err
}

ToIntToBool 等宽松入口会忽略转换错误并返回目标类型零值。输入来自请求、配置或外部系统时,优先使用 E 版本。

泛型转换

根包提供统一的泛型入口:

type User struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

user, err := mconv.ToE[User](map[string]any{
	"id":   "7",
	"name": "maltose",
})

numbers, err := mconv.ToSliceTE[int]([]string{"1", "2", "3"})
labels, err := mconv.ToMapTE[int, string](map[string]int{"1": 10})

忽略错误的对应入口为 To[T]ToSliceT[T]ToMapT[K,V]

泛型 map 直接转换原始键,不经过字符串中转,因此可以保留任意可比较键:

type Key struct{ ID int }

result, err := mconv.ToMapTE[Key, int](map[Key]string{
	{ID: 1}: "42",
})

结构体转换

ToE[T] 适合新代码,ToStructE 适合需要复用已有目标对象的场景:

type Profile struct {
	Name      string `mconv:"display_name"`
	Age       int    `json:"age"`
	Enabled   bool   `yaml:"enabled"`
	CreatedAt time.Time
}

profile := Profile{Enabled: true}
err := mconv.ToStructE(map[string]any{
	"display_name": "Alice",
	"age":          "18",
	"CreatedAt":    "2026-08-24T12:00:00Z",
}, &profile)

结构体转换规则:

  • 标签优先级为 mconvjsonyaml,支持 - 和逗号选项。
  • 精确键匹配优先,其次进行大小写不敏感匹配。
  • 外层字段优先于匿名嵌入字段;同一深度的同名字段会返回歧义错误。
  • 匿名字段带显式标签时保持嵌套,不进行字段提升。
  • 多级指针、用户自定义基础类型、数组、slice、map 和嵌套结构体使用相同转换语义。
  • 转换先在隔离副本中完成;任何字段失败时,原目标对象保持不变。
  • map 键转换发生碰撞时返回错误,避免静默覆盖数据。

自定义 Hook

Hook 在默认的字符串时间、字符串时长转换之后执行:

hook := func(from, to reflect.Type, data any) (any, error) {
	if from.Kind() == reflect.Int && to.Kind() == reflect.String {
		return fmt.Sprintf("status-%d", data.(int)), nil
	}
	return data, nil
}

value, err := mconv.ToE[string](1, hook)

Hook 返回原值表示继续转换,返回新值表示交给后续 Hook 或内置转换处理,返回错误会终止整个转换。

错误处理

错误哨兵和 ConversionError 位于根包,可配合 errors.Iserrors.As

_, err := mconv.ToInt8E(128)
if errors.Is(err, mconv.ErrOverflow) {
	// handle overflow
}

var conversionErr *mconv.ConversionError
if errors.As(err, &conversionErr) {
	fmt.Println(conversionErr.TargetType)
	fmt.Println(conversionErr.Path)
}

嵌套错误包含完整路径,例如 Users[0].Age。公开哨兵包括:

  • ErrUnsupportedType
  • ErrConversionFailed
  • ErrOverflow
  • ErrInvalidTimeFormat
  • ErrInvalidJSONFormat

JSON

jsonText, err := mconv.ToJSONE(map[string]any{"name": "maltose"})

var user User
err = mconv.FromJSONE(jsonText, &user)

data, err := mconv.ToMapFromJSONE(jsonText)

缓存策略

结构体字段计划由库自动缓存,无需配置。

字符串和时间值缓存默认关闭。基准显示字符串转换本身比加锁查询缓存更快;时间缓存只在少量热点字符串被高频重复解析时有收益。确认业务输入具有低基数特征后,可以主动开启时间缓存:

mconv.SetTimeCacheSize(100)
defer mconv.SetTimeCacheSize(0)

SetStringCacheSize 为兼容和实验场景保留。SetTypeInfoCacheSizeSetConversionCacheSizeClearTypeInfoCacheClearConversionCache 已废弃并保留为空操作,后续主版本会删除。

性能

以下数据来自 Apple M2,命令为 go test -run '^$' -bench . -benchmem。结果会随 Go 版本和机器变化:

BenchmarkToString-8             ~21 ns/op       3 B/op      1 allocs/op
BenchmarkToSliceT-8            ~160 ns/op     136 B/op      7 allocs/op
BenchmarkToMapT-8              ~404 ns/op     488 B/op     12 allocs/op
BenchmarkStructConversion-8    ~318 ns/op      48 B/op      1 allocs/op

时间缓存的典型权衡:重复值约 75 ns/op,关闭缓存约 98 ns/op;高基数输入开启缓存约 340 ns/op,关闭缓存约 109 ns/op。请用实际输入分布决定是否开启。

开发与验证

go test -race ./...
go vet ./...
go test -run '^$' -bench . -benchmem

CI 同时验证 Go 1.18 和当前稳定版,在稳定版运行 fuzz 冒烟测试,并检查 basic 覆盖率、分配预算和相对最新 v1 标签的公共 API 兼容性。定时 Benchmark 会保存可下载的性能结果,用于跨提交执行 benchstat 对比。

许可证

MIT

Documentation

Overview

Package mconv converts scalar values, containers, JSON, and structs with a consistent error model. The root package is the canonical public API.

Functions ending in E return conversion errors and are preferred for data from requests, configuration, storage, or other external systems. Their convenience counterparts return the target type's zero value on failure.

Example
package main

import (
	"fmt"

	"github.com/graingo/mconv"
)

func main() {
	fmt.Println(mconv.ToString(42))
	fmt.Println(mconv.ToBool("yes"))
	fmt.Println(mconv.ToInt("invalid"))
}
Output:
42
true
0

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrUnsupportedType   = internal.ErrUnsupportedType
	ErrConversionFailed  = internal.ErrConversionFailed
	ErrOverflow          = internal.ErrOverflow
	ErrInvalidTimeFormat = internal.ErrInvalidTimeFormat
	ErrInvalidJSONFormat = internal.ErrInvalidJSONFormat
)

Functions

func ClearAllCaches

func ClearAllCaches()

ClearAllCaches clears all conversion caches.

func ClearConversionCache

func ClearConversionCache()

ClearConversionCache is retained for source compatibility. Deprecated: direct type checks are faster than a separate conversion cache.

func ClearStringCache

func ClearStringCache()

ClearStringCache clears the string conversion cache.

func ClearTimeCache

func ClearTimeCache()

ClearTimeCache clears the time conversion cache.

func ClearTypeInfoCache

func ClearTypeInfoCache()

ClearTypeInfoCache is retained for source compatibility. Deprecated: mconv uses an automatic decoder cache and has no separate type-info cache.

func FromJSON

func FromJSON(jsonStr string, target interface{})

FromJSON converts JSON into target.

func FromJSONE

func FromJSONE(jsonStr string, target interface{}) error

FromJSONE converts JSON into target with error.

func SetConversionCacheSize

func SetConversionCacheSize(size int)

SetConversionCacheSize is retained for source compatibility. Deprecated: direct type checks are faster than a separate conversion cache.

func SetStringCacheSize

func SetStringCacheSize(size int)

SetStringCacheSize sets the optional string conversion cache size. The cache is disabled by default; a non-positive size disables it.

func SetTimeCacheSize

func SetTimeCacheSize(size int)

SetTimeCacheSize sets the optional time conversion cache size. The cache is disabled by default; a non-positive size disables it.

func SetTypeInfoCacheSize

func SetTypeInfoCacheSize(size int)

SetTypeInfoCacheSize is retained for source compatibility. Deprecated: mconv uses an automatic decoder cache and has no separate type-info cache.

func To added in v1.2.0

func To[T any](value interface{}, hooks ...HookFunc) T

To converts value to T and returns the zero value when conversion fails.

func ToBool

func ToBool(value interface{}) bool

ToBool converts any type to bool.

func ToBoolE

func ToBoolE(value interface{}) (bool, error)

ToBoolE converts any type to bool with error.

func ToComplex64

func ToComplex64(value interface{}) complex64

ToComplex64 converts any type to complex64.

func ToComplex64E

func ToComplex64E(value interface{}) (complex64, error)

ToComplex64E converts any type to complex64 with error.

func ToComplex128

func ToComplex128(value interface{}) complex128

ToComplex128 converts any type to complex128.

func ToComplex128E

func ToComplex128E(value interface{}) (complex128, error)

ToComplex128E converts any type to complex128 with error.

func ToDuration added in v0.1.2

func ToDuration(value interface{}) time.Duration

ToDuration converts any type to time.Duration.

func ToDurationE added in v0.1.2

func ToDurationE(value interface{}) (time.Duration, error)

ToDurationE converts any type to time.Duration with error.

func ToE added in v1.2.0

func ToE[T any](value interface{}, hooks ...HookFunc) (T, error)

ToE converts value to T and returns a conversion error with path context.

Example
package main

import (
	"fmt"

	"github.com/graingo/mconv"
)

func main() {
	type user struct {
		ID   int    `json:"id"`
		Name string `json:"name"`
	}

	converted, err := mconv.ToE[user](map[string]interface{}{
		"id":   "7",
		"name": "Maltose",
	})
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("%d %s\n", converted.ID, converted.Name)
}
Output:
7 Maltose

func ToFloat32

func ToFloat32(value interface{}) float32

ToFloat32 converts any type to float32.

func ToFloat32E

func ToFloat32E(value interface{}) (float32, error)

ToFloat32E converts any type to float32 with error.

func ToFloat64

func ToFloat64(value interface{}) float64

ToFloat64 converts any type to float64.

func ToFloat64E

func ToFloat64E(value interface{}) (float64, error)

ToFloat64E converts any type to float64 with error.

func ToFloat64Map

func ToFloat64Map(value interface{}) map[string]float64

ToFloat64Map converts any type to a float64 map.

func ToFloat64MapE

func ToFloat64MapE(value interface{}) (map[string]float64, error)

ToFloat64MapE converts any type to a float64 map with error.

func ToFloat64Slice

func ToFloat64Slice(value interface{}) []float64

ToFloat64Slice converts any type to a float64 slice.

func ToFloat64SliceE

func ToFloat64SliceE(value interface{}) ([]float64, error)

ToFloat64SliceE converts any type to a float64 slice with error.

func ToInt

func ToInt(value interface{}) int

ToInt converts any type to int.

func ToInt8

func ToInt8(value interface{}) int8

ToInt8 converts any type to int8.

func ToInt8E

func ToInt8E(value interface{}) (int8, error)

ToInt8E converts any type to int8 with error.

func ToInt16

func ToInt16(value interface{}) int16

ToInt16 converts any type to int16.

func ToInt16E

func ToInt16E(value interface{}) (int16, error)

ToInt16E converts any type to int16 with error.

func ToInt32

func ToInt32(value interface{}) int32

ToInt32 converts any type to int32.

func ToInt32E

func ToInt32E(value interface{}) (int32, error)

ToInt32E converts any type to int32 with error.

func ToInt64

func ToInt64(value interface{}) int64

ToInt64 converts any type to int64.

func ToInt64E

func ToInt64E(value interface{}) (int64, error)

ToInt64E converts any type to int64 with error.

func ToIntE

func ToIntE(value interface{}) (int, error)

ToIntE converts any type to int with error.

func ToIntMap

func ToIntMap(value interface{}) map[string]int

ToIntMap converts any type to an int map.

func ToIntMapE

func ToIntMapE(value interface{}) (map[string]int, error)

ToIntMapE converts any type to an int map with error.

func ToIntSlice

func ToIntSlice(value interface{}) []int

ToIntSlice converts any type to an int slice.

func ToIntSliceE

func ToIntSliceE(value interface{}) ([]int, error)

ToIntSliceE converts any type to an int slice with error.

func ToJSON

func ToJSON(value interface{}) string

ToJSON converts any type to JSON.

func ToJSONE

func ToJSONE(value interface{}) (string, error)

ToJSONE converts any type to JSON with error.

func ToMap

func ToMap(value interface{}) map[string]interface{}

ToMap converts any type to a map.

func ToMapE

func ToMapE(value interface{}) (map[string]interface{}, error)

ToMapE converts any type to a map with error.

func ToMapFromJSON

func ToMapFromJSON(jsonStr string) map[string]interface{}

ToMapFromJSON converts JSON to a map.

func ToMapFromJSONE

func ToMapFromJSONE(jsonStr string) (map[string]interface{}, error)

ToMapFromJSONE converts JSON to a map with error.

func ToMapT added in v1.2.0

func ToMapT[K comparable, V any](value interface{}) map[K]V

ToMapT converts value to map[K]V and returns nil when conversion fails.

func ToMapTE added in v1.2.0

func ToMapTE[K comparable, V any](value interface{}) (map[K]V, error)

ToMapTE converts value to map[K]V and returns a conversion error with key context.

func ToSlice

func ToSlice(value interface{}) []interface{}

ToSlice converts any type to slice.

func ToSliceE

func ToSliceE(value interface{}) ([]interface{}, error)

ToSliceE converts any type to slice with error.

func ToSliceFromJSON

func ToSliceFromJSON(jsonStr string) []interface{}

ToSliceFromJSON converts JSON to a slice.

func ToSliceFromJSONE

func ToSliceFromJSONE(jsonStr string) ([]interface{}, error)

ToSliceFromJSONE converts JSON to a slice with error.

func ToSliceT added in v1.2.0

func ToSliceT[T any](value interface{}) []T

ToSliceT converts value to []T and returns nil when conversion fails.

func ToSliceTE added in v1.2.0

func ToSliceTE[T any](value interface{}) ([]T, error)

ToSliceTE converts value to []T and returns a conversion error with index context.

func ToString

func ToString(value interface{}) string

ToString converts any type to string.

func ToStringE

func ToStringE(value interface{}) (string, error)

ToStringE converts any type to string with error.

func ToStringMap

func ToStringMap(value interface{}) map[string]string

ToStringMap converts any type to a string map.

func ToStringMapE

func ToStringMapE(value interface{}) (map[string]string, error)

ToStringMapE converts any type to a string map with error.

func ToStringSlice

func ToStringSlice(value interface{}) []string

ToStringSlice converts any type to a string slice.

func ToStringSliceE

func ToStringSliceE(value interface{}) ([]string, error)

ToStringSliceE converts any type to a string slice with error.

func ToStruct added in v1.1.3

func ToStruct(source, pointer interface{}, hooks ...HookFunc)

ToStruct converts a map or struct to a struct.

func ToStructE added in v1.1.3

func ToStructE(source, pointer interface{}, hooks ...HookFunc) error

ToStructE converts a map or struct to a struct with error.

func ToTime

func ToTime(value interface{}, formats ...string) time.Time

ToTime converts any type to time.Time.

func ToTimeE

func ToTimeE(value interface{}, formats ...string) (time.Time, error)

ToTimeE converts any type to time.Time with error.

func ToUint

func ToUint(value interface{}) uint

ToUint converts any type to uint.

func ToUint8

func ToUint8(value interface{}) uint8

ToUint8 converts any type to uint8.

func ToUint8E

func ToUint8E(value interface{}) (uint8, error)

ToUint8E converts any type to uint8 with error.

func ToUint16

func ToUint16(value interface{}) uint16

ToUint16 converts any type to uint16.

func ToUint16E

func ToUint16E(value interface{}) (uint16, error)

ToUint16E converts any type to uint16 with error.

func ToUint32

func ToUint32(value interface{}) uint32

ToUint32 converts any type to uint32.

func ToUint32E

func ToUint32E(value interface{}) (uint32, error)

ToUint32E converts any type to uint32 with error.

func ToUint64

func ToUint64(value interface{}) uint64

ToUint64 converts any type to uint64.

func ToUint64E

func ToUint64E(value interface{}) (uint64, error)

ToUint64E converts any type to uint64 with error.

func ToUintE

func ToUintE(value interface{}) (uint, error)

ToUintE converts any type to uint with error.

Types

type ConversionError added in v1.2.0

type ConversionError = internal.ConversionError

ConversionError describes a failed conversion and its destination path.

Example
package main

import (
	"errors"
	"fmt"

	"github.com/graingo/mconv"
)

func main() {
	_, err := mconv.ToInt8E(128)
	fmt.Println(errors.Is(err, mconv.ErrOverflow))

	var conversionErr *mconv.ConversionError
	if errors.As(err, &conversionErr) {
		fmt.Println(conversionErr.TargetType)
	}
}
Output:
true
int8

type HookFunc added in v1.1.1

type HookFunc = complex.HookFunc

HookFunc is an alias of complex.HookFunc.

Directories

Path Synopsis
Package basic implements scalar conversions used by mconv.
Package basic implements scalar conversions used by mconv.
Package complex implements container, JSON, generic, and struct conversions.
Package complex implements container, JSON, generic, and struct conversions.

Jump to

Keyboard shortcuts

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