Comments (3)
现有需求来自一下几段代码:
// ekit/ben/copier/copy.go
// Copier 复制数据
// 1. 深拷贝亦或是浅拷贝,取决于具体的实现。每个实现都要声明清楚这一点;
// 2. Src 和 Dst 都必须是普通的结构体,支持组合
// 3. 只复制公共字段
// 这种设计设计,即使用 *Src 和 *Dst 可能加剧内存逃逸
type Copier[Src any, Dst any] interface {
// CopyTo 将 src 中的数据复制到 dst 中
CopyTo(src *Src, dst *Dst) error
// Copy 将创建一个 Dst 的实例,并且将 Src 中的数据复制过去
Copy(src *Src) (*Dst, error)
}
// reflectCopier 基于反射的实现
// reflectCopier 是浅拷贝
type reflectCopier[Src any, Dst any] struct {
// ....
}
// CopyTo 执行复制
// 执行复制的逻辑是:
// 1. 按照字段的映射关系进行匹配
// 2. 如果 Src 和 Dst 中匹配的字段,其类型是基本类型(及其指针)或者内置类型(及其指针),并且类型一样,则直接用 Src 的值
// 3. 如果 Src 和 Dst 中匹配的字段,其类型都是结构体,或者都是结构体指针,那么会深入复制
// 4. 否则,返回类型不匹配的错误
// TODO: 支持不同类型之间的转换
func (r *reflectCopier[Src, Dst]) CopyTo(src *Src, dst *Dst) error {
// ....
}
需求澄清
- “公共字段”的定义是什么?或两个结构体中的某个字段是否“匹配”的定义是什么?
现阶段的理解是,两个结构体中某一字段名称、类型及相对位置均相同,即为匹配/公共字段
type Src struct {
A string
b int
c bool
D int32
E error
F user
}
type Dst struct {
A string
b int
c *bool
D string
E error
F *user
}
type user struct {}
匹配字段为A,b,E
不匹配字段为c,D
F是否认定为匹配?
- 非导出字段如何处理? 是否忽略?
如果忽略非导出字段,上例中匹配字段为A,E;不匹配字段为D
- 不匹配字段的处理细节
通常来说会忽略不匹配字段,但有一种特殊情况就是两个类型没有任何公共/匹配字段是否应该报错?
- API设计,我为NewReflectCopier添加了error,用户按照如下代码使用可以吗?
copier, err := NewReflectCopier[Src, Dst]()
if err != nil {
// 至少要有一个匹配字段
// Src/Dst类型非法等
// Src/Dst中某字段类型为多级指针
}
err = copier.CopyTo(......)
if err != nil {
// 复制时发生的错误
}
from ekit.
公共字段我写错了,应该是公开字段。
- 同类型的指针和非指针,在目前这位同学的设计里面是不匹配的。你可以尝试改进这个东西,去除”匹配“的概念。也就是我们引入 converter 的概念。例如,对于一些字段来说,用户可以要求 user 可以被转化过去 *user 甚至 **user 等。以及基本类型之间的转换。可以尝试给用户更加强的控制手段
- 非导出字段直接忽略,不管
- 两个类型没有任何匹配字段可以报错
- 可以,应该是我忘记加了,按照我的使用习惯,我永远都要有 error
from ekit.
接下来还有两个方向的优化点:
- 一个是自定义字段映射关系:例如忽略某个字段,组合的话用 "A.B.C"这样来指定忽略什么;例如我有一个字段叫做 User1 我映射过去 User2 上;
- 不同类型的字段直接的转换:例如基本类型的转化,指针和非指针的转换,string 其它基本类型,以及 []byte 的转换
还可以考虑的是,提供校验手段:
- 例如当某个字段映射过去另外一个字段的时候,可以顺手校验一下字段对不对。不过这个需要校验器模块的支持,我记得开源有,但是我还没去关注它的实现好不好
from ekit.
Related Issues (20)
- Tuple: 新增 Pair 和 Triple 两种类型 HOT 8
- retry: Strategy 接口设计与等间隔重试实现
- retry: 指数退避重试策略实现 HOT 1
- pool相关总issue
- sqlx:ScanRows 和 ScanAll方法 HOT 9
- mapx: MutipleTreeMap
- mapx: 为 MultipleMap 添加 PutVals 方法
- mapx: LinkedMap 特性 HOT 12
- copier: ReflectCopier 支持忽略字段 HOT 1
- copier: 支持类型转换 HOT 20
- randx: 随机验证码生成器 HOT 5
- ekit:AnyValue 支持类型转换 - String 转数字类型
- unsafe 转换 string 和 []byte HOT 1
- sqlx: sqlx.NewNullXXX 方法
- syncx: SegmentKeysLock HOT 3
- slice.ContainsFunc破坏性修改确认 HOT 3
- mapx: 支持 Len 方法
- 重构randx.RandCode以及传入的RandType数值 HOT 3
- slice 转 map HOT 3
- 提供 Must 和 MustT 函数,简化错误处理 HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ekit.