Giter VIP home page Giter VIP logo

Comments (3)

longyue0521 avatar longyue0521 commented on June 21, 2024

@flycash

现有需求来自一下几段代码:

// 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 {
       // ....
}

需求澄清

  1. “公共字段”的定义是什么?或两个结构体中的某个字段是否“匹配”的定义是什么?

现阶段的理解是,两个结构体中某一字段名称、类型及相对位置均相同,即为匹配/公共字段

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是否认定为匹配?

  1. 非导出字段如何处理? 是否忽略?

如果忽略非导出字段,上例中匹配字段为A,E;不匹配字段为D

  1. 不匹配字段的处理细节

通常来说会忽略不匹配字段,但有一种特殊情况就是两个类型没有任何公共/匹配字段是否应该报错?

  1. API设计,我为NewReflectCopier添加了error,用户按照如下代码使用可以吗?
copier, err := NewReflectCopier[Src, Dst]()
if err != nil {
      // 至少要有一个匹配字段
      // Src/Dst类型非法等
      // Src/Dst中某字段类型为多级指针
}

err = copier.CopyTo(......)
if err != nil {
     // 复制时发生的错误
} 

from ekit.

flycash avatar flycash commented on June 21, 2024

公共字段我写错了,应该是公开字段。

  1. 同类型的指针和非指针,在目前这位同学的设计里面是不匹配的。你可以尝试改进这个东西,去除”匹配“的概念。也就是我们引入 converter 的概念。例如,对于一些字段来说,用户可以要求 user 可以被转化过去 *user 甚至 **user 等。以及基本类型之间的转换。可以尝试给用户更加强的控制手段
  2. 非导出字段直接忽略,不管
  3. 两个类型没有任何匹配字段可以报错
  4. 可以,应该是我忘记加了,按照我的使用习惯,我永远都要有 error

from ekit.

flycash avatar flycash commented on June 21, 2024

接下来还有两个方向的优化点:

  • 一个是自定义字段映射关系:例如忽略某个字段,组合的话用 "A.B.C"这样来指定忽略什么;例如我有一个字段叫做 User1 我映射过去 User2 上;
  • 不同类型的字段直接的转换:例如基本类型的转化,指针和非指针的转换,string 其它基本类型,以及 []byte 的转换

还可以考虑的是,提供校验手段:

  • 例如当某个字段映射过去另外一个字段的时候,可以顺手校验一下字段对不对。不过这个需要校验器模块的支持,我记得开源有,但是我还没去关注它的实现好不好

from ekit.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.