Go克隆几种方式

简介: Go克隆几种方式

Go克隆几种方式


序列化的方式实现深度拷贝

最简单的方式是基于序列化和反序列化来实现对象的深度复制:

func deepCopy(dst, src interface{}) error {
    var buf bytes.Buffer
    if err := gob.NewEncoder(&buf).Encode(src); err != nil {
        return err
    }
    return gob.NewDecoder(bytes.NewBuffer(buf.Bytes())).Decode(dst)
}


测试用例


import (
 "bytes"
 "encoding/gob"
 "encoding/json"
 "fmt"
 "log"
 "reflect"
 "testing"
 "github.com/mohae/deepcopy"
)
type Basics struct {
 A string
 B int
 C []string
}
func TestClone1(t *testing.T) {
 var src2 = &Basics{
  A: "hello world",
  B: 34,
  C: []string{"1213", "1312"},
 }
 dst := new(Basics)
 if err := deepCopy(dst, src2); err != nil {
  log.Fatal(err)
 }
 log.Printf("%+v", dst)
}


执行结果:


=== RUN   TestClone1
2021/12/23 10:37:56 &{A:hello world B:34 C:[1213 1312]}
--- PASS: TestClone1 (0.00s)
PASS


反射实现深度拷贝


深度复制可以基于reflect包的反射机制完成, 但是全部重头手写的话会很繁琐.

/深度克隆,可以克隆任意数据类型
func DeepClone(src interface{}) (interface{}, error) {
 typ := reflect.TypeOf(src)
 if typ.Kind() == reflect.Ptr {
  typ = typ.Elem()
  dst := reflect.New(typ).Elem()
  b, _ := json.Marshal(src)
  if err := json.Unmarshal(b, dst.Addr().Interface()); err != nil {
   return nil, err
  }
  return dst.Addr().Interface(), nil
 } else {
  dst := reflect.New(typ).Elem()
  b, _ := json.Marshal(src)
  if err := json.Unmarshal(b, dst.Addr().Interface()); err != nil {
   return nil, err
  }
  return dst.Interface(), nil
 }
}


测试用例


import (
 "bytes"
 "encoding/gob"
 "encoding/json"
 "fmt"
 "log"
 "reflect"
 "testing"
 "github.com/mohae/deepcopy"
)
type Basics struct {
 A string
 B int
 C []string
}
func TestDeepClone(t *testing.T) {
 var src = &Basics{
  A: "hello world",
  B: 34,
  C: []string{"1213", "1312"},
 }
 dst, _ := DeepClone(src)
 fmt.Println(dst)
}


执行结果:


=== RUN   TestDeepClone
&{hello world 34 [1213 1312]}
--- PASS: TestDeepClone (0.00s)
PASS


借助包深拷贝


"github.com/mohae/deepcopy"

使用方式如下:


dst := deepcopy.Copy(src)


测试用例


import "github.com/mohae/deepcopy"
type BasicsSmall struct {
 a string
 b int
 c []string
}
func TestDeepCopy(t *testing.T) {
 //src := &User{Name: "xiaomng", Age: 100}
 var src = &BasicsSmall{
  a: "hello world",
  b: 34,
  c: []string{"1213", "1312"},
 }
 dst := deepcopy.Copy(src)
 fmt.Println(dst)
}


测试结果:


=== RUN   TestDeepCopy
&{ 0 []}
--- PASS: TestDeepCopy (0.00s)
PASS


为啥会出现上面的结果,因为 struct 结构,首字母都是小写的!!!

换个用例


import "github.com/mohae/deepcopy"
type User struct {
 Name string // 小写变量,不能被deepCopy函数拷贝成功
 Age  int
}
func TestDeepCopy(t *testing.T) {
 src := &User{Name: "xiaomng", Age: 100}
 //var src = &BasicsSmall{
 // a: "hello world",
 // b: 34,
 // c: []string{"1213", "1312"},
 //}
 dst := deepcopy.Copy(src)
 fmt.Println(dst)
}


执行结果:


=== RUN   TestDeepCopy
&{xiaomng 100}
--- PASS: TestDeepCopy (0.00s)
PASS


总结

上述拷贝有个问题,结构体中有小写成员变量时,上述方式无效。

相关文章
|
Web App开发 JavaScript 程序员
|
5月前
|
SQL 数据库连接 Go
Go语言数据库编程:GORM 的基本使用
GORM 是 Go 语言最流行的 ORM 框架,封装了 database/sql,支持自动迁移、关联关系、事务等功能,开发体验接近高层语言的 ORM。本文介绍了 GORM 的安装与初始化、模型定义、自动迁移、基本 CRUD 操作、条件构造器、钩子函数、事务处理、日志调试等内容,帮助开发者快速掌握其使用方法。
|
存储 Go API
使用GoFrame连接和操作TDengine时序数据库
通过使用GoFrame框架和TDengine Go驱动,我们可以方便地连接和操作TDengine时序数据库。无论是插入、查询还是分析时序数据,都可以通过简单的API调用来实现。GoFrame提供了强大的Web开发功能,结合TDengine的高性能时序数据存储和查询能力,可以构建高效、可扩展的时序数据应用。
307 5
|
3月前
|
存储 编解码 开发者
基于STM32和OLED的小恐龙游戏项目设计与实现【免费开源】
小恐龙游戏最初是作为浏览器离线小游戏而广为人知,其简单的操作与生动的画面使其深受用户喜爱。本项目将经典的小恐龙跳跃游戏移植到嵌入式平台上,使用STM32微控制器作为核心控制器,OLED屏幕进行显示,搭配按键或触摸实现用户交互。通过本项目,既可以体验游戏开发在嵌入式系统上的实现方式,又能掌握STM32 GPIO、定时器、OLED驱动、按键扫描及简单动画实现技术。
基于STM32和OLED的小恐龙游戏项目设计与实现【免费开源】
|
10月前
|
vr&ar 图形学 云计算
实时云渲染与虚拟现实的结合:推动3D设计行业向更广阔领域拓展
3D设计行业面临四大难题:渲染时间长、审批流程复杂、成本高且设备更新快、渲染时电脑无法处理其他工作。实时云渲染通过云端算力,提供快速便捷的渲染解决方案,支持多人协同审批,大幅降低硬件成本,提高工作效率。平行云作为国内领先的实时云渲染服务商,已在全球范围内服务上千家企业,涵盖教育培训、数字孪生、医疗健康等多领域,助力3D设计行业高效解决现有难题。
299 18
|
算法 调度 决策智能
基于自适应遗传算法的车间调度matlab仿真,可以任意调整工件数和机器数,输出甘特图
这是一个使用MATLAB2022a实现的自适应遗传算法解决车间调度问题的程序,能调整工件数和机器数,输出甘特图和适应度收敛曲线。程序通过编码初始化、适应度函数、遗传操作(选择、交叉、变异)及自适应机制进行优化,目标如最小化完工时间。算法在迭代过程中动态调整参数,以提升搜索效率和全局优化。
|
小程序 前端开发 JavaScript
微信小程序|英语学习交流平台小程序
微信小程序|英语学习交流平台小程序
280 1
|
存储 算法 计算机视觉
Qt5 和 OpenCV4 计算机视觉项目:1~5(2)
Qt5 和 OpenCV4 计算机视觉项目:1~5(2)
268 0
Golang:deepcopy深拷贝工具库
Golang:deepcopy深拷贝工具库
1043 0
|
监控 关系型数据库 应用服务中间件
zabbix自定义监控、钉钉、邮箱报警
zabbix自定义监控、钉钉、邮箱报警,实验准备,安装,添加监控对象,添加自定义监控项,监控mariadb,监控NGINX,钉钉报警设置,邮件报警
671 0