脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Golang - golang 对象深拷贝的常见方式及性能

golang 对象深拷贝的常见方式及性能

2022-10-23 16:20whoops本尊 Golang

这篇文章主要介绍了golang 对象深拷贝的常见方式及性能,Go语言中所有赋值操作都是值传递,如果结构中不含指针,则直接赋值就是深度拷贝,文章围绕主题展开更多相关资料,需要的小伙伴可以参考一下

关于golang拷贝的概念

Go语言中所有赋值操作都是值传递,如果结构中不含指针,则直接赋值就是深度拷贝;如果结构中含有指针(包括自定义指针,以及切片,map等使用了指针的内置类型),则数据源和拷贝之间对应指针会共同指向同一块内存,这时深度拷贝需要特别处理。目前,有三种方法,一是用gob序列化成字节序列再反序列化生成克隆对象;二是先转换成json字节序列,再解析字节序列生成克隆对象;三是针对具体情况,定制化拷贝。前两种方法虽然比较通用但是因为使用了reflex反射,性能比定制化拷贝要低出2个数量级,所以在性能要求较高的情况下应该尽量避免使用前两者。

完整代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package json
import (
   "bytes"
   "encoding/gob"
   "encoding/json"
   "fmt"
   "testing"
)
/**
 * @Description: 请求信息
 */
type BidRequest struct {
   ID     string  `json:"id"`
   Imp    []*Imp  `json:"imp"`
   Device *Device `json:"device"`
}
/**
 * @Description: imp对象
 */
type Imp struct {
   ID          string  `json:"id"`
   Tagid       string  `json:"tagid"`
   Bidfloor    float64 `json:"bidfloor"`
}
/**
 * @Description: 设备信息
 */
type Device struct {
   Ua         string `json:"ua"`
   IP         string `json:"ip"`
   Geo        *Geo   `json:"geo"`
   Make       string `json:"make"`
   Model      string `json:"model"`
   Os         string `json:"os"`
   Osv        string `json:"osv"`
}
/**
 * @Description: 地理位置信息
 */
type Geo struct {
   Lat     int    `json:"lat"`
   Lon     int    `json:"lon"`
   Country string `json:"country"`
   Region  string `json:"region"`
   City    string `json:"city"`
}
/**
 * @Description: 利用gob进行深拷贝
 */
func DeepCopyByGob(src,dst interface{}) error {
   var buffer bytes.Buffer
   if err := gob.NewEncoder(&buffer).Encode(src); err != nil {
      return err
   }
   return gob.NewDecoder(&buffer).Decode(dst)
}
/**
 * @Description: 利用json进行深拷贝
 */
func DeepCopyByJson(src,dst *BidRequest) error{
   if tmp, err := json.Marshal(&src);err!=nil{
      return err
   }else {
      err = json.Unmarshal(tmp, dst)
      return err
   }
}
 
/**
 * @Description: 通过自定义进行copy
 */
func DeepCopyByCustom(src,dst *BidRequest){
   dst.ID=src.ID
   dst.Device=&Device{
      Ua: src.Device.Ua,
      IP: src.Device.IP,
      Geo: &Geo{
         Lat: src.Device.Geo.Lat,
         Lon: src.Device.Geo.Lon,
      },
      Make: src.Device.Make,
      Model: src.Device.Model,
      Os: src.Device.Os,
      Osv: src.Device.Osv,
   }
   dst.Imp=make([]*Imp,len(src.Imp))
   for index,imp:=range src.Imp{
      //注意此处因为imp对象里无指针对象,所以可以直接使用等于
      dst.Imp[index]=imp
   }
}
 
func initData()*BidRequest  {
   str:="{"id":"MM7dIXz4H05qtmViqnY5dW","imp":[{"id":"1","tagid":"3979722720","bidfloor":0.01}],"device":{"ua":"Mozilla/5.0 (Linux; Android 10; SM-G960N Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/92.0.4515.115 Mobile Safari/537.36 (Mobile; afma-sdk-a-v212621039.212621039.0)","ip":"192.168.1.0","geo":{"lat":0,"lon":0,"country":"KOR","region":"KR-11","city":"Seoul"},"make":"samsung","model":"sm-g960n","os":"android","osv":"10"}}"
   ans:=new(BidRequest)
   json.Unmarshal([]byte(str),&ans)
   return ans
}
 
/**
 * @Description: 压测深拷贝 -gob
 */
func BenchmarkDeepCopy_Gob(b *testing.B)  {
   src:=initData()
   b.ResetTimer()
   for i:=0;i<b.N;i++{
      DeepCopyByGob(src,new(BidRequest))
   }
}
 
/**
 * @Description: 压测深拷贝 -json
 */
func BenchmarkDeepCopy_Json(b *testing.B)  {
   src:=initData()
   b.ResetTimer()
   for i:=0;i<b.N;i++{
      DeepCopyByJson(src,new(BidRequest))
   }
}
/**
 * @Description: 压测深拷贝 -custom
 */
func BenchmarkDeepCopy_custom(b *testing.B)  {
   src:=initData()
   b.ResetTimer()
   for i:=0;i<b.N;i++{
      DeepCopyByCustom(src,new(BidRequest))
   }
}
/**
 * @Description: 测试拷贝是否ok
 */
func TestCpoyIsOk(t *testing.T)  {
   src:=initData()
   //1.gob
   dst01:=new(BidRequest)
   DeepCopyByGob(src,dst01)
   bs01, _ := json.Marshal(dst01)
   fmt.Printf("%v\n",string(bs01))
   //2.json
   dst02:=new(BidRequest)
   DeepCopyByJson(src,dst02)
   bs02, _ := json.Marshal(dst02)
   fmt.Printf("%v\n",string(bs02))
   //3.custom
   dst03:=new(BidRequest)
   DeepCopyByCustom(src,dst03)
   bs03, _ := json.Marshal(dst02)
   fmt.Printf("%v\n",string(bs03))
}

先执行 TestCpoyIsOk,验证三种方式的输出是否ok,其验证结果如下:

golang 对象深拷贝的常见方式及性能

benmark三种copy方式:

golang 对象深拷贝的常见方式及性能

执行命令 go test -bench=. -benchmem 可以同时查看到每次操作的内存和耗时的情况

总结

可以看到 从性能上来讲 custom>json>gob,从代码数量上来讲 gob>json>custom ,因此具体使用时应该充分考虑性能和代码复杂度,若性能要求不是很高建议gob方法,其比较简洁并且利于生成工具包,若要求性能则尽量使用custom,此处不偷懒可以提高性能哦。若是性能要求在中间,则可以使用json先序列化,再反序列化赋值。

到此这篇关于golang 对象深拷贝的常见方式及性能的文章就介绍到这了,更多相关golang 深拷贝内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://juejin.cn/post/7110861544698675208

延伸 · 阅读

精彩推荐
  • GolangGolang使用zlib压缩和解压缩字符串

    Golang使用zlib压缩和解压缩字符串

    本文给大家分享的是Golang使用zlib压缩和解压缩字符串的方法和示例,有需要的小伙伴可以参考下 ...

    rfyiamcool9552020-05-06
  • Golang一个小时学会用 Go 创建命令行工具

    一个小时学会用 Go 创建命令行工具

    最近因为项目需要写了一段时间的 Go ,相对于 Java 来说语法简单同时又有着一些 Python 之类的语法糖,让人大呼”真香“。但现阶段相对来说还是 Python 写...

    Go语言中文网1722020-12-08
  • GolangGo语言使用钉钉机器人推送消息的实现示例

    Go语言使用钉钉机器人推送消息的实现示例

    本文主要介绍了Go语言使用钉钉机器人推送消息的实现示例,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    何其涛9592021-11-14
  • GolangGo语言sort包函数使用示例

    Go语言sort包函数使用示例

    这篇文章主要为大家介绍了Go语言sort包函数使用示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪...

    Notomato9482022-10-13
  • Golang特殊字符的json序列化总结大全

    特殊字符的json序列化总结大全

    这篇文章主要给大家介绍了关于特殊字符的json序列化的相关资料,通过示例代码分别给大家介绍了关于python 、 rust 、 java 和golang对特殊字符的json序列化操...

    wu_sphinx5842020-05-19
  • GolangGo语言学习笔记之文件读写操作详解

    Go语言学习笔记之文件读写操作详解

    这篇文章主要为大家详细介绍了Go语言对文件进行读写操作的方法,文中的示例代码讲解详细,对我们学习Go语言有一定的帮助,需要的可以参考一下...

    剑客阿良_ALiang8302022-10-10
  • Golanggolang抓取网页并分析页面包含的链接方法

    golang抓取网页并分析页面包含的链接方法

    今天小编就为大家分享一篇golang抓取网页并分析页面包含的链接方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 ...

    仰天笑8852020-05-27
  • GolangGo语言开发必知的一个内存模型细节

    Go语言开发必知的一个内存模型细节

    这篇文章主要为大家介绍了Go语言开发必知的一个内存模型细节详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪...

    煎鱼3592022-07-14