Skip to content
Merged
2 changes: 1 addition & 1 deletion constant.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package mapper

const (
packageVersion = "0.7.14"
packageVersion = "0.8"
mapperTagKey = "mapper"
jsonTagKey = "json"
IgnoreTagValue = "-"
Expand Down
79 changes: 79 additions & 0 deletions example/func/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Mapper 函数式泛型示例

本示例展示如何使用 `mapper_func.go` 中的函数式泛型 API 进行对象映射。

## 功能特点

- **MapDirect**: 直接返回映射结果,无需传入目标对象
- **MapDirectPtr**: 指针版本,处理指针输入
- **MapDirectSlice**: 批量映射 slice
- **MapDirectPtrSlice**: 指针切片批量映射
- **SafeMapDirect**: 带错误处理的映射
- **SafeMapDirectSlice**: 带错误处理的批量映射
- **字段映射缓存**: 重复映射时自动使用缓存提升性能

## 使用方法

```bash
# 运行示例
cd example/func
go run main.go
```

## 示例代码

```go
package main

import (
"fmt"
"github.com/devfeel/mapper"
)

type User struct {
ID int64 `mapper:"id"`
Name string `mapper:"name"`
Email string `mapper:"email"`
}

type UserDTO struct {
ID int64 `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}

func main() {
// 单次映射
user := User{ID: 1, Name: "张三", Email: "test@example.com"}
dto := mapper.MapDirect[User, UserDTO](user)
fmt.Printf("%+v\n", dto)

// 批量映射
users := []User{
{ID: 1, Name: "用户1", Email: "user1@example.com"},
{ID: 2, Name: "用户2", Email: "user2@example.com"},
}
dtos := mapper.MapDirectSlice[User, UserDTO](users)
fmt.Printf("%+v\n", dtos)
}
```

## 性能说明

MapDirect 系列函数使用字段映射缓存:
- 首次映射时构建字段映射关系并缓存
- 后续映射自动使用缓存,减少反射调用
- 批量映射时性能提升明显(约 7x)

## 与传统方式对比

| 方式 | 代码风格 | 性能 |
|------|----------|------|
| Map (传统) | 需要传入目标对象指针 | 反射开销较大 |
| MapDirect (函数式) | 直接返回结果 | 有缓存优化,性能更好 |

## 注意事项

1. 源类型和目标类型字段名相同且类型相同才会映射
2. 支持 `mapper` tag 进行字段名映射
3. 批量操作建议使用 `MapDirectSlice` 以获得最佳性能
178 changes: 178 additions & 0 deletions example/func/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
package main

import (
"fmt"
"github.com/devfeel/mapper"
)

// 定义测试用的结构体
type (
// 源结构体 - 用户信息
User struct {
ID int64 `mapper:"id"`
Name string `mapper:"name"`
Email string `mapper:"email"`
Age int `mapper:"age"`
CreatedAt int64 `mapper:"created_at"`
Score float64
}

// 目标结构体 - 用户DTO
UserDTO struct {
ID int64 `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
Age int `json:"age"`
CreatedAt int64 `json:"created_at"`
Score float64 `json:"score"`
}

// 目标结构体 - 用户VO (不同字段)
UserVO struct {
UserID int64 `json:"user_id"`
UserName string `json:"user_name"`
Email string `json:"email"`
Age int `json:"age"`
CreatedAt int64 `json:"created_at"`
Score float64 `json:"score"`
}
)

func main() {
fmt.Println("=== Mapper 函数式泛型示例 (MapDirect) ===")
fmt.Println()

// 示例1: MapDirect 同构类型映射
fmt.Println("1. MapDirect 同构类型映射")
user1 := User{
ID: 1,
Name: "张三",
Email: "zhangsan@example.com",
Age: 28,
CreatedAt: 1704067200,
Score: 95.5,
}
userCopy := mapper.MapDirect[User, User](user1)
fmt.Printf(" 源: %+v\n", user1)
fmt.Printf(" 副本: %+v\n", userCopy)
fmt.Println()

// 示例2: MapDirect 异构类型映射
fmt.Println("2. MapDirect 异构类型映射 (User -> UserDTO)")
user2 := User{
ID: 2,
Name: "李四",
Email: "lisi@example.com",
Age: 32,
CreatedAt: 1704153600,
Score: 88.0,
}
userDTO := mapper.MapDirect[User, UserDTO](user2)
fmt.Printf(" User: %+v\n", user2)
fmt.Printf(" UserDTO: %+v\n", userDTO)
fmt.Println()

// 示例3: MapDirectPtr 指针版本
fmt.Println("3. MapDirectPtr 指针版本")
user3 := &User{
ID: 3,
Name: "王五",
Email: "wangwu@example.com",
Age: 35,
CreatedAt: 1704240000,
Score: 92.0,
}
userDTO3 := mapper.MapDirectPtr[User, UserDTO](user3)
fmt.Printf(" 源指针: %+v\n", user3)
fmt.Printf(" 目标: %+v\n", userDTO3)
fmt.Println()

// 示例4: MapDirectSlice 批量映射
fmt.Println("4. MapDirectSlice 批量映射")
users := []User{
{ID: 1, Name: "用户1", Email: "user1@example.com", Age: 20, CreatedAt: 1704067200, Score: 85.0},
{ID: 2, Name: "用户2", Email: "user2@example.com", Age: 25, CreatedAt: 1704153600, Score: 90.0},
{ID: 3, Name: "用户3", Email: "user3@example.com", Age: 30, CreatedAt: 1704240000, Score: 95.0},
}
userDTOs := mapper.MapDirectSlice[User, UserDTO](users)
fmt.Printf(" 源数量: %d, 目标数量: %d\n", len(users), len(userDTOs))
for i, u := range userDTOs {
fmt.Printf(" [%d] %+v\n", i, u)
}
fmt.Println()

// 示例5: MapDirectPtrSlice 指针切片映射
fmt.Println("5. MapDirectPtrSlice 指针切片映射")
userPtrs := []*User{
{ID: 10, Name: "赵六", Email: "zhaoliu@example.com", Age: 40, CreatedAt: 1704326400, Score: 80.0},
{ID: 11, Name: "孙七", Email: "sunqi@example.com", Age: 45, CreatedAt: 1704412800, Score: 85.5},
}
userDTOPtrs := mapper.MapDirectPtrSlice[User, UserDTO](userPtrs)
fmt.Printf(" 源数量: %d, 目标数量: %d\n", len(userPtrs), len(userDTOPtrs))
for i, u := range userDTOPtrs {
if u != nil {
fmt.Printf(" [%d] %+v\n", i, *u)
}
}
fmt.Println()

// 示例6: SafeMapDirect 带错误处理的映射
fmt.Println("6. SafeMapDirect 带错误处理")
user6 := User{
ID: 6,
Name: "周八",
Email: "zhouba@example.com",
Age: 50,
CreatedAt: 1704499200,
Score: 98.0,
}
userDTO6, err := mapper.SafeMapDirect[User, UserDTO](user6)
if err != nil {
fmt.Printf(" 错误: %v\n", err)
} else {
fmt.Printf(" UserDTO: %+v\n", userDTO6)
}
fmt.Println()

// 示例7: SafeMapDirectSlice 批量安全映射
fmt.Println("7. SafeMapDirectSlice 批量安全映射")
users7 := []User{
{ID: 7, Name: "吴九", Email: "wujiu@example.com", Age: 22, CreatedAt: 1704585600, Score: 87.0},
{ID: 8, Name: "郑十", Email: "zhengshi@example.com", Age: 27, CreatedAt: 1704672000, Score: 93.0},
}
userDTOs7, err := mapper.SafeMapDirectSlice[User, UserDTO](users7)
if err != nil {
fmt.Printf(" 错误: %v\n", err)
} else {
fmt.Printf(" 源数量: %d, 目标数量: %d\n", len(users7), len(userDTOs7))
for i, u := range userDTOs7 {
fmt.Printf(" [%d] %+v\n", i, u)
}
}
fmt.Println()

// 示例8: 性能对比演示
fmt.Println("8. 性能对比 (缓存效果)")
largeUsers := make([]User, 1000)
for i := 0; i < 1000; i++ {
largeUsers[i] = User{
ID: int64(i),
Name: fmt.Sprintf("User%d", i),
Email: fmt.Sprintf("user%d@example.com", i),
Age: 20 + i%50,
CreatedAt: 1704067200 + int64(i*86400),
Score: float64(60 + i%40),
}
}

// 第一次调用(缓存未命中)
result1 := mapper.MapDirectSlice[User, UserDTO](largeUsers)
fmt.Printf(" 首次映射 1000 条: %d 条\n", len(result1))

// 第二次调用(缓存命中,应该更快)
result2 := mapper.MapDirectSlice[User, UserDTO](largeUsers)
fmt.Printf(" 二次映射 1000 条: %d 条\n", len(result2))
fmt.Println()

fmt.Println("=== 示例完成 ===")
}
Loading
Loading