docs: finalize docs and sync cast dependency to v1.0.1

This commit is contained in:
Star 2026-04-22 10:45:41 +08:00
parent a006caffa6
commit 6ccd35c41a
6 changed files with 66 additions and 60 deletions

43
AI.md
View File

@ -5,42 +5,39 @@
## 🤖 AI 行为准则 ## 🤖 AI 行为准则
1. **优先使用 convert.To 进行对象映射**在需要进行结构体拷贝、Map 转 Struct 或复杂嵌套转换时,直接调用 `convert.To(from, &to)` 1. **优先使用 convert.To 进行对象映射**在需要进行结构体拷贝、Map 转 Struct 或复杂嵌套转换时,直接调用 `convert.To(from, &to)`
2. **不再建议手动编写冗余转换代码**:例如不需要手动循环切片来转换元素类型,`convert.To` 会自动完成 2. **理解“解包”与“包装”逻辑**:生成代码时可以放心将单值传给切片目标,或将切片传给单值目标
3. **理解“解包”与“包装”逻辑**:生成代码时可以放心将单值传给切片目标,或将切片传给单值目标 3. **利用键名容忍度**:在处理不可控的外部数据时,无需担心键名格式(驼峰、蛇形等),`convert.To` 会自动匹配
4. **利用键名容忍度**:在处理不可控的外部 Map 数据(如 API 响应)时,无需担心键名是 `camelCase` 还是 `snake_case``convert.To` 会自动匹配 4. **无视指针层级**:在编写调用代码时,无需手动解引用或取地址以匹配类型,`convert` 内部会自动穿透处理
## 🛠 关键 API 逻辑约定 ## 🛠 关键 API 逻辑约定
| 函数 | 逻辑特征 | | 函数 | 逻辑特征 |
| :--- | :--- | | :--- | :--- |
| `To(from, to)` | **主入口**`to` 必须为指针。支持所有基础类型、容器、函数及嵌套指针。失败会重置 `to` 为零值而不报错。 | | `To(from, to)` | **主入口**。要求 `to` 必须为指针。核心逻辑是根据 `to` 的类型强力揉捏 `from`。 |
| `normalizeKey` | 内部逻辑:移除所有非字母数字字符并转小写。`My_User-ID` -> `myuserid`。 | | `Convert(from, to)` | `To` 的别名。 |
| `Func` 转换 | 动态代理。支持在不同签名的函数间建立桥接,并自动转换输入输出参数。 | | `FlatStruct(data)` | 获取结构体的扁平化元信息(导出字段/方法)。 |
| `FlatStruct` | 工具。返回包含所有平展字段、方法及其 Value 的 `StructInfo`。 |
## 🧩 典型模式 (Best Practices) ## 🧩 典型模式 (Best Practices)
* **❌ 不推荐 (Standard Go)**: * **❌ 不推荐 (Standard Go)**:
```go ```go
// 手动循环并转换类型 // 手动映射字段,且对格式敏感
dest := make([]int, len(src))
for i, v := range src {
dest[i] = int(cast.Int(v))
}
```
* **✅ 推荐 (@go/convert)**:
```go
// 一行搞定,自动处理所有摩擦
convert.To(src, &dest)
```
* **❌ 不推荐 (Standard Go)**:
```go
// 手动映射字段
u.UserID = m["user_id"].(int) u.UserID = m["user_id"].(int)
``` ```
* **✅ 推荐 (@go/convert)**: * **✅ 推荐 (@go/convert)**:
```go ```go
// 自动忽略键名格式差异 // 自动匹配任何格式的键名
convert.To(m, &u) convert.To(m, &u)
``` ```
* **❌ 不推荐 (Standard Go)**:
```go
// 手动处理单值转切片
var dest []int
dest = append(dest, src)
```
* **✅ 推荐 (@go/convert)**:
```go
// 自动包装
convert.To(src, &dest)
```

13
CHANGELOG.md Normal file
View File

@ -0,0 +1,13 @@
# Changelog: @go/convert
## [v1.0.0] - 2026-04-22
### Added
- **核心映射引擎**:基于反射的深度对象转换功能,支持 Struct, Map, Slice。
- **意图优先设计**:支持单值与切片的自动包装/解包转换。
- **智能字符串转换**:支持将 CSV 格式字符串 (`"a,b,c"`) 自动转为切片。
- **极致去摩擦匹配**:键名映射时自动忽略大小写及所有非字母数字字符(如 `_`, `-`, `#` 等)。
- **函数桥接器**:支持将一个函数转换为另一个签名的函数,并自动处理参数转换。
- **Parse 钩子**:支持通过 `ParseXxx` 方法定制特定字段的转换逻辑。
- **平展工具**:提供 `FlatStruct` 辅助函数用于获取结构体的扁平化字段信息。
- **接口兼容**:原生支持 `json.Unmarshaler``yaml.Unmarshaler`

View File

@ -4,21 +4,34 @@
## 🎯 设计哲学 ## 🎯 设计哲学
* **消除类型摩擦**:在业务代码中,我们经常遇到单值与切片、字符串与结构体之间的转换。`convert` 能够自动处理这些“形状”差异(如将单值包装成切片,或将切片解包为单值) * **消除类型摩擦**:在业务代码中,我们经常遇到单值与切片、字符串与结构体之间的转换。`convert` 能够自动处理这些“形状”差异。
* **极致容忍 Key 名**Map 键名可能是 `user_id`,也可能是 `UserId``convert` 在映射时会忽略所有非字母数字字符及大小写,确保映射成功 * **极致容忍 Key 名**:忽略所有非字母数字字符及大小写,确保不同来源的数据都能精准映射。
* **指针透明化**无论是 `int` 映射到 `*string`,还是 `***int` 映射到 `int``convert` 都会自动处理深层指针的穿透与分配。 * **指针透明化**:自动处理深层指针的穿透与分配。
* **可定制转换**支持 `ParseXxx` 方法作为转换钩子,允许对象在被映射时执行特定的解析逻辑。 * **可定制转换**通过方法钩子实现特定的解析逻辑。
## 🚀 核心特性 ## 🛠 API Reference
* **深度映射**:支持 Struct、Map、Slice 之间的无限层级嵌套转换。 ### 核心函数
* **智能切片转换**
* 单值 -> 切片:自动包装为 `[]T{val}` #### `func To(from, to any)`
* 切片 -> 单值:自动取首个元素。 `from` 中的数据深度映射到 `to` 中。`to` 必须是一个**指针**类型。
* CSV 字符串 -> 切片:支持 `"1,2,3"` 风格的自动拆分。 - **支持类型**基础类型互转、Struct 互转、Map 转 Struct、Struct 转 Map、Slice 互转等。
* **函数转换**:支持将一个函数转换为另一个签名的函数,并在调用时自动转换参数和返回值。 - **去摩擦特性**:支持单值与切片的互转(包装/解包、CSV 字符串转切片。
* **接口支持**:兼容 `json.Unmarshaler``yaml.Unmarshaler`
* **平展工具**:提供 `FlatStruct` 工具,可将复杂的嵌套结构体平展为扁平的字段列表。 #### `func Convert(from, to any)`
`To` 的别名,用于保持向前兼容。
### 结构体分析
#### `func FlatStruct(data any) *StructInfo`
平展结构体。返回导出字段、导出方法及其对应的 `reflect.Value` 映射。
#### `func FlatStructWithUnexported(data any) *StructInfo`
平展结构体,包含未导出的字段和方法。
### 定制转换钩子
如果目标结构体定义了 `func (p *T) ParseXxx(v any) FieldType` 方法(其中 `Xxx` 为字段名),`convert` 将优先调用该方法来决定字段的值。
## 📦 安装 ## 📦 安装
@ -31,25 +44,13 @@ go get apigo.cc/go/convert
```go ```go
import "apigo.cc/go/convert" import "apigo.cc/go/convert"
// 1. 极致去摩擦的键名匹配 // 1. 模糊键名匹配
from := map[string]any{"user_id": 1001, "USER-NAME": "Andy"} from := map[string]any{"user-id": 1001}
type User struct { UserID int; UserName string } var u struct { UserID int }
var u User convert.To(from, &u) // u.UserID = 1001
convert.To(from, &u) // u.UserID = 1001, u.UserName = "Andy"
// 2. 切片自动解包 // 2. 切片自动解包
nums := []int{100, 200} nums := []int{100, 200}
var n int var n int
convert.To(nums, &n) // n = 100 convert.To(nums, &n) // n = 100
// 3. 智能 CSV 解析
tags := "tag1, tag2, tag3"
var tagList []string
convert.To(tags, &tagList) // ["tag1", "tag2", "tag3"]
// 4. 函数动态映射
f1 := func(a int) int { return a + 1 }
var f2 func(string) string
convert.To(f1, &f2)
fmt.Println(f2("10")) // "11"
``` ```

View File

@ -22,8 +22,3 @@
| 函数 | 平均耗时 | 性能分析 | | 函数 | 平均耗时 | 性能分析 |
| :--- | :--- | :--- | | :--- | :--- | :--- |
| `MatrixConvert` | **1226 ns/op** | 包含反射解析、Map 键名归一化及嵌套映射,性能处于工业级水准。 | | `MatrixConvert` | **1226 ns/op** | 包含反射解析、Map 键名归一化及嵌套映射,性能处于工业级水准。 |
## 🔍 Self-Review 修正记录
1. **代码纠错**:移除了未使用变量 `fromArg`
2. **逻辑补强**:在基础类型转换分支中引入了 `effectiveFrom` 解包逻辑,支持切片到单值的自动转换。
3. **命名一致性**:统一使用 `To` 作为主入口,`Convert` 作为别名。

2
go.mod
View File

@ -3,6 +3,6 @@ module apigo.cc/go/convert
go 1.25.0 go 1.25.0
require ( require (
apigo.cc/go/cast v1.0.0 apigo.cc/go/cast v1.0.1
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )

4
go.sum
View File

@ -1,5 +1,5 @@
apigo.cc/go/cast v1.0.0 h1:MhkWBDMq8ewAxn5PYHUlIuwpfsW5bQS6ueptBkim5hc= apigo.cc/go/cast v1.0.1 h1:OCQepSPf+wQBawUc4LB0hv4WegWyyz66qELsKuzzl6I=
apigo.cc/go/cast v1.0.0/go.mod h1:vh9ZqISCmTUiyinkNMI/s4f045fRlDK3xC+nPWQYBzI= apigo.cc/go/cast v1.0.1/go.mod h1:vh9ZqISCmTUiyinkNMI/s4f045fRlDK3xC+nPWQYBzI=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=