2

原型模式补遗 - Go语言中的深度拷贝

 10 months ago
source link: https://colobu.com/2023/08/07/deep-copy-in-go/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

原型模式补遗 - Go语言中的深度拷贝

在前一篇真实世界的Go设计模式 - 原型模式一文中,我们介绍了gorm作者张金柱的另一个库jinzhu/copier,它提供了对象数据深度复制的能力。

在和网友的交流中,有网友提到金柱的那个库不支持any类型的深度复制,也提到也有叫做DeepCopy库支持,但又不支持指针深度拷贝。真的是这么样,或者说当前还有这种现象么?我写了一个测试程序,分别对指针、map、slice和接口进行了测试,发现这些库其实都支持了各种类型的深度复制。代码太长我就不专门贴在这里了,大家可以访问下面的网址查看测试代码:https://go.dev/play/p/WoringjBHeZ .

当然,对于jinzhu/copier,你需要显示指定深度拷贝参数,否则使用默认的Copy还是不能够复制接口、map等对象。jinzhu/copier还提供不同类型的对象之间的复制,功能更强大,代码也就更复杂。

这些深度拷贝的库如下:

相比较而言,mohae/deepcopy的代码也更简洁易懂,也被将近一万多个github项目锁使用。
唯一比较遗憾的是,这个项目将近6年没有更新了,一方面说明稳定,另一方面也说明Go的一些新的特性也没有应用在它的方面,设置它连个go.mod都没有。

我复制了这个项目,准备维护下去。你可以关注 smallnest/deepcopy

目前我为它增加了泛型的支持, 避免了手工的type assertion,也增加channel的复制能力。

cpy := deepcopy.Copy[T](orig)

所以一个完整的例子如下:

complexData := ComplexStruct{
ID: 1,
Name: "Complex Object",
Description: "A struct with various types for JSON benchmarking",
IsEnabled: true,
Count: 5,
Price: 99.99,
Tags: []string{"tag1", "tag2", "tag3"},
CreatedAt: "2023-08-07T12:34:56Z",
Options: map[string]bool{"option1": true, "option2": false, "option3": true},
Nested: NestedStruct{
Field1: 42,
Field2: "Nested Field",
ItemAStruct: ItemAStruct{
ItemID: 100,
ItemName: "Item A",
ItemBStruct: &ItemBStruct{
ItemType: "Item Type",
ItemFrom: "Item From",
Items: []ItemStruct{
{ItemID: 101, ItemName: "Item 1"},
{ItemID: 102, ItemName: "Item 2"},
ExtraData: json.RawMessage(`{"key": "value"}`),
Handler: func(w http.ResponseWriter, r *http.Request) {},
Opts: map[string]any{
"opt1": "value1",
"opt2": 2,
"opt3": true,
newData := Copy[ComplexStruct](complexData)

channel类型只复制channel类型和它的容量,并没有复制channel中的元素:一是并没有方式直接获取缓存在channel中的元素,二是channel中的元素总是在变化之中,复制过来的元素也许在channel中已经被取走了。它也没有复制channel的状态,原channel被close了,复制的新channel也没有被close。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK