mconv

package module
v1.1.4 Latest Latest
Warning

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

Go to latest
Published: Jul 17, 2025 License: MIT Imports: 3 Imported by: 8

README

mconv

中文 | English

一个轻量级的高性能 Go 类型转换库。

安装

go get github.com/graingo/mconv

特性

  • 简单直观的 API
  • 零依赖
  • 全面的类型转换支持
  • 线程安全
  • 高性能缓存机制
  • 泛型支持(Go 1.18+)
  • 反射结果缓存

基本用法

// 基本类型转换
str := mconv.ToString(123)        // "123"
num := mconv.ToInt("123")         // 123
b := mconv.ToBool(1)              // true
f := mconv.ToFloat64("123.45")    // 123.45
t := mconv.ToTime("2006-01-02")   // time.Time

// 带错误处理
str, err := mconv.ToStringE(123)  // "123", nil
num, err := mconv.ToIntE("abc")   // 0, error

// 复杂类型转换
slice := mconv.ToSlice([]int{1, 2, 3})  // []interface{}{1, 2, 3}
strSlice := mconv.ToStringSlice([]int{1, 2, 3}) // []string{"1", "2", "3"}
m := mconv.ToMap(map[string]int{"a": 1}) // map[string]interface{}{"a": 1}

// JSON 转换
jsonStr := mconv.ToJSON(map[string]interface{}{"name": "John"}) // {"name":"John"}
personMap := mconv.ToMapFromJSON(`{"name":"Jane"}`) // map[string]interface{}{"name": "Jane"}

高级结构体转换

mconv 包在 complex 子包中提供了一个强大的 Struct 函数 (以及它返回错误的版本 StructE)。这个工具专为将 map[string]interface{} 或其他 struct 灵活、高性能地转换为目标 struct 而设计。它利用缓存机制来优化重复转换,从而实现显著的速度提升。

主要特性:

  • 简单转换: 直接将数据映射到结构体的字段。
  • 标签驱动映射: 使用 mconv 标签来映射不同名称的字段。
  • 不区分大小写: 自动匹配源 map 中的键和结构体字段,不限制大小写。
  • 嵌套结构体: 递归地转换嵌套的 mapstruct
  • 通过钩子扩展: 提供自定义的 HookFunc 函数来处理特殊的转换逻辑。
  • 高性能: 缓存结构体的分析结果,使得后续的转换非常快。

基础用法

package main

import (
	"fmt"
	"github.com/graingo/mconv/complex"
)

func main() {
	type User struct {
		ID   int    `mconv:"user_id"`
		Name string `mconv:"user_name"`
	}

	source := map[string]interface{}{
		"user_id":   123,
		"USER_NAME": "Alice", // 不区分大小写匹配
	}

	var user User
	err := complex.ToStructE(source, &user)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%+v\n", user)
	// Output: {ID:123 Name:Alice}
}

使用钩子 (Hooks)

您可以使用钩子注入自定义的转换逻辑。例如,将一个整型的状态转换为字符串。

package main

import (
	"fmt"
	"github.com/graingo/mconv/complex"
	"reflect"
)

func main() {
	type Post struct {
		Title  string
		Status string `mconv:"status"`
	}

	// 这个钩子将整型 status 转换为字符串表示
	intStatusToStringHook := func(from reflect.Type, to reflect.Type, data interface{}) (interface{}, error) {
		if from.Kind() == reflect.Int && to.Kind() == reflect.String {
			i, _ := data.(int)
			switch i {
			case 0:
				return "Draft", nil
			case 1:
				return "Published", nil
			default:
				return "Unknown", nil
			}
		}
		return data, nil
	}

	source := map[string]interface{}{
		"Title":  "Hello World",
		"status": 1,
	}

	var post Post
	err := complex.ToStructE(source, &post, intStatusToStringHook)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%+v\n", post)
	// Output: {Title:Hello World Status:Published}
}

默认情况下, mconv 包含一个内置钩子,用于处理从 stringtime.Time 的转换。

泛型支持(Go 1.18+)

import "github.com/graingo/mconv/complex"

// 使用泛型进行切片转换
strSlice := complex.ToSliceT[string]([]int{1, 2, 3}) // []string{"1", "2", "3"}
intSlice := complex.ToSliceT[int]([]string{"1", "2", "3"}) // []int{1, 2, 3}

// 使用泛型进行映射转换
strMap := complex.ToMapT[string, string](map[string]int{"a": 1}) // map[string]string{"a": "1"}
intMap := complex.ToMapT[string, int](map[string]interface{}{"a": "1"}) // map[string]int{"a": 1}

性能优化

// 设置缓存大小
mconv.SetStringCacheSize(2000)       // 设置字符串缓存大小(默认 1000)
mconv.SetTimeCacheSize(200)          // 设置时间缓存大小(默认 100)
mconv.SetTypeInfoCacheSize(1000)     // 设置类型信息缓存大小(默认 1000)
mconv.SetConversionCacheSize(1000)   // 设置转换缓存大小(默认 1000)

// 清除缓存
mconv.ClearStringCache()             // 清除字符串缓存
mconv.ClearTimeCache()               // 清除时间缓存
mconv.ClearTypeInfoCache()           // 清除类型信息缓存
mconv.ClearConversionCache()         // 清除转换缓存
mconv.ClearAllCaches()               // 清除所有缓存

基准测试结果

以下基准测试结果在 Apple M2 处理器上测量:

BenchmarkToString-8                 13534419               107.5 ns/op            8 B/op           1 allocs/op
BenchmarkToInt-8                    100000000               10.91 ns/op            0 B/op           0 allocs/op
BenchmarkToBool-8                   178200254                6.75 ns/op            0 B/op           0 allocs/op
BenchmarkToFloat64-8                54603055                20.84 ns/op            0 B/op           0 allocs/op
BenchmarkToTime-8                   15548144                76.57 ns/op           32 B/op           1 allocs/op
BenchmarkToSlice-8                  35479252                33.26 ns/op           40 B/op           2 allocs/op
BenchmarkToStringSlice-8             3392653               364.7 ns/op           120 B/op           8 allocs/op
BenchmarkToMap-8                     7964676               153.1 ns/op           336 B/op           2 allocs/op
BenchmarkToJSON-8                    3466358               348.2 ns/op           192 B/op           7 allocs/op

泛型函数:

BenchmarkToSliceT-8                  2906990               397.6 ns/op          136 B/op           6 allocs/op
BenchmarkToMapT-8                    1654909               723.4 ns/op          688 B/op           7 allocs/op

结构体转换:

BenchmarkStructConversion-8              7186039           166.4 ns/op          0 B/op          0 allocs/op
BenchmarkStructConversionParallel-8     36372223            40.26 ns/op         0 B/op          0 allocs/op

反射缓存性能优势

反射缓存是 mconv 库的一个重要特性,它可以显著提高类型转换的性能。以下基准测试结果展示了反射缓存的性能优势:

BenchmarkReflectionCache_TypeInfo/WithoutCache-8           8842224               133.9 ns/op            56 B/op           7 allocs/op
BenchmarkReflectionCache_TypeInfo/WithCache-8             25792029                49.03 ns/op            0 B/op           0 allocs/op

从上述结果可以看出:

  1. 性能提升:使用反射缓存后,处理相同类型的反射操作速度提高了约 2.7 倍(从 133.9 ns/op 降至 49.03 ns/op)。
  2. 内存优化:使用缓存后,内存分配从每次操作 56 字节和 7 次分配减少到 0 字节和 0 次分配,完全消除了内存分配开销。
  3. 吞吐量提升:每秒可处理的操作数从约 880 万增加到约 2580 万,提高了约 192%。

对于大型数据结构,性能优势更加明显:

BenchmarkLargeSliceConversion/WithoutCache-8                  9327             121340 ns/op         46738 B/op        1747 allocs/op
BenchmarkLargeSliceConversion/WithCache-8                     9620             121506 ns/op         46738 B/op        1747 allocs/op

这些优势在处理大型数据集或需要频繁进行类型转换的应用中尤为明显。反射缓存通过存储类型信息和转换结果,避免了重复的反射操作,从而显著提高了性能。

使用场景

反射缓存在以下场景中特别有用:

  1. API 服务:需要频繁将数据在不同格式之间转换
  2. 数据处理管道:处理大量结构相似的数据
  3. ORM 和数据映射:在数据库记录和结构体之间进行映射
  4. 配置处理:解析和转换各种格式的配置数据
  5. JSON/XML 处理:频繁进行序列化和反序列化操作

许可证

MIT 许可证

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ToString convert any type to string.
	ToString = basic.ToString
	// ToStringE convert any type to string with error.
	ToStringE = basic.ToStringE

	// ToInt convert any type to int.
	ToInt = basic.ToInt
	// ToIntE convert any type to int with error.
	ToIntE = basic.ToIntE
	// ToInt64 convert any type to int64.
	ToInt64 = basic.ToInt64
	// ToInt64E convert any type to int64 with error.
	ToInt64E = basic.ToInt64E
	// ToInt32 convert any type to int32.
	ToInt32 = basic.ToInt32
	// ToInt32E convert any type to int32 with error.
	ToInt32E = basic.ToInt32E
	// ToInt16 convert any type to int16.
	ToInt16 = basic.ToInt16
	// ToInt16E convert any type to int16 with error.
	ToInt16E = basic.ToInt16E
	// ToInt8 convert any type to int8.
	ToInt8 = basic.ToInt8
	// ToInt8E convert any type to int8 with error.
	ToInt8E = basic.ToInt8E

	// ToUint convert any type to uint.
	ToUint = basic.ToUint
	// ToUintE convert any type to uint with error.
	ToUintE = basic.ToUintE
	// ToUint64 convert any type to uint64.
	ToUint64 = basic.ToUint64
	// ToUint64E convert any type to uint64 with error.
	ToUint64E = basic.ToUint64E
	// ToUint32 convert any type to uint32.
	ToUint32 = basic.ToUint32
	// ToUint32E convert any type to uint32 with error.
	ToUint32E = basic.ToUint32E
	// ToUint16 convert any type to uint16.
	ToUint16 = basic.ToUint16
	// ToUint16E convert any type to uint16 with error.
	ToUint16E = basic.ToUint16E
	// ToUint8 convert any type to uint8.
	ToUint8 = basic.ToUint8
	// ToUint8E convert any type to uint8 with error.
	ToUint8E = basic.ToUint8E

	// ToFloat64 convert any type to float64.
	ToFloat64 = basic.ToFloat64
	// ToFloat64E convert any type to float64 with error.
	ToFloat64E = basic.ToFloat64E
	// ToFloat32 convert any type to float32.
	ToFloat32 = basic.ToFloat32
	// ToFloat32E convert any type to float32 with error.
	ToFloat32E = basic.ToFloat32E

	// ToBool convert any type to bool.
	ToBool = basic.ToBool
	// ToBoolE convert any type to bool with error.
	ToBoolE = basic.ToBoolE

	// ToComplex128 convert any type to complex128.
	ToComplex128 = basic.ToComplex128
	// ToComplex128E convert any type to complex128 with error.
	ToComplex128E = basic.ToComplex128E
	// ToComplex64 convert any type to complex64.
	ToComplex64 = basic.ToComplex64
	// ToComplex64E convert any type to complex64 with error.
	ToComplex64E = basic.ToComplex64E
	// ToTime convert any type to time.Time.
	ToTime = basic.ToTime
	// ToTimeE convert any type to time.Time with error.
	ToTimeE = basic.ToTimeE
	// ToDuration convert any type to time.Duration.
	ToDuration = basic.ToDuration
	// ToDurationE convert any type to time.Duration with error.
	ToDurationE = basic.ToDurationE
)
View Source
var (
	// ToSlice convert any type to slice.
	ToSlice = complex.ToSlice
	// ToSliceE convert any type to slice with error.
	ToSliceE = complex.ToSliceE
	// ToStringSlice convert any type to slice of string.
	ToStringSlice = complex.ToStringSlice
	// ToStringSliceE convert any type to slice of string with error.
	ToStringSliceE = complex.ToStringSliceE
	// ToIntSlice convert any type to slice of int.
	ToIntSlice = complex.ToIntSlice
	// ToIntSliceE convert any type to slice of int with error.
	ToIntSliceE = complex.ToIntSliceE
	// ToFloat64Slice convert any type to slice of float64.
	ToFloat64Slice = complex.ToFloat64Slice
	// ToFloat64SliceE convert any type to slice of float64 with error.
	ToFloat64SliceE = complex.ToFloat64SliceE

	// ToMap convert any type to map.
	ToMap = complex.ToMap
	// ToMapE convert any type to map with error.
	ToMapE = complex.ToMapE
	// ToStringMap convert any type to map of string.
	ToStringMap = complex.ToStringMap
	// ToStringMapE convert any type to map of string with error.
	ToStringMapE = complex.ToStringMapE
	// ToIntMap convert any type to map of int.
	ToIntMap = complex.ToIntMap
	// ToIntMapE convert any type to map of int with error.
	ToIntMapE = complex.ToIntMapE
	// ToFloat64Map convert any type to map of float64.
	ToFloat64Map = complex.ToFloat64Map
	// ToFloat64MapE convert any type to map of float64 with error.
	ToFloat64MapE = complex.ToFloat64MapE

	// ToJSON convert any type to json.
	ToJSON = complex.ToJSON
	// ToJSONE convert any type to json with error.
	ToJSONE = complex.ToJSONE
	// FromJSON convert json to any type.
	FromJSON = complex.FromJSON
	// FromJSONE convert json to any type with error.
	FromJSONE = complex.FromJSONE
	// ToMapFromJSON convert json to map.
	ToMapFromJSON = complex.ToMapFromJSON
	// ToMapFromJSONE convert json to map with error.
	ToMapFromJSONE = complex.ToMapFromJSONE
	// ToSliceFromJSON convert json to slice.
	ToSliceFromJSON = complex.ToSliceFromJSON
	// ToSliceFromJSONE convert json to slice with error.
	ToSliceFromJSONE = complex.ToSliceFromJSONE

	// ToStruct convert map or struct to struct.
	ToStruct = complex.ToStruct
	// ToStructE convert map or struct to struct with error.
	ToStructE = complex.ToStructE
)
View Source
var (
	SetStringCacheSize = internal.SetStringCacheSize
	SetTimeCacheSize   = internal.SetTimeCacheSize
	ClearStringCache   = internal.ClearStringCache
	ClearTimeCache     = internal.ClearTimeCache
	ClearAllCaches     = internal.ClearAllCaches

	// Reflection cache
	SetTypeInfoCacheSize   = internal.SetTypeInfoCacheSize
	SetConversionCacheSize = internal.SetConversionCacheSize
	ClearTypeInfoCache     = internal.ClearTypeInfoCache
	ClearConversionCache   = internal.ClearConversionCache
)

Export cache related functions

Functions

This section is empty.

Types

type HookFunc added in v1.1.1

type HookFunc = complex.HookFunc

HookFunc is an alias of complex.HookFunc.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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