赞
踩
各编程语言都有深浅拷贝的概念, 它们的核心是拷贝的是地址
(浅拷贝)还是值
(深拷贝), 今天我们就对其概念介绍, 并做性能对比和特性对比
地址
. 新老对象共享内存Slice(无论原生类型或结构体slice), Map
内容
, 会创建新对象, 新老对象不共享内存Struct, Array, Int, String, Float, Bool
当我们需要拷贝一个新对象时, 怎么选择呢? 显然
a := b
即可有Reflect, GobEncode, JsonMarshal几种方式, 我们做一个Benchmark试验如下
type InnerStruct struct {
Int int
String string
}
type CType struct {
Int int
String string
Struct InnerStruct
IntSlice []int
StringSlice []string
StructSlice []InnerStruct
IntArray [2]int
StringArray [2]string
StructArray [2]InnerStruct
Map map[string]string
}
c := &CType{
Int: 1,
String: "2",
Struct: InnerStruct{Int: 3, String: "4"},
IntSlice: []int{5, 6},
StringSlice: []string{"7", "8"},
StructSlice: []InnerStruct{{Int: 9, String: "10"}, {Int: 11, String: "12"}},
IntArray: [2]int{13, 14},
StringArray: [2]string{"15", "16"},
StructArray: [2]InnerStruct{{Int: 17, String: "18"}, {Int: 19, String: "20"}},
Map: map[string]string{"21": "22", "23": "24"},
}
测试电脑为cpu: Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
func BenchmarkShallowCopy(b *testing.B) {
for n := 0; n < b.N; n++ {
c.ShallowCopy()
}
}
结果为BenchmarkShallowCopy 0.7702 ns/op
func BenchmarkReflect(b *testing.B) {
for n := 0; n < b.N; n++ {
c.DeepCopyReflect()
}
}
结果为BenchmarkReflect 4515 ns/op
func BenchmarkJsonMarshal(b *testing.B) {
for n := 0; n < b.N; n++ {
c.DeepCopyJsonMarshal()
}
}
结果为BenchmarkJsonMarshal 11133 ns/op
func BenchmarkGobMarshal(b *testing.B) {
for n := 0; n < b.N; n++ {
c.DeepCopyGobMarshal()
}
}
结果为BenchmarkGobMarshal 54298 ns/op
综上, 浅拷贝
性能>Reflect
性能>JsonMarshal
性能>GobMarshal
做完性能对别后, 我们还需对别深浅拷贝是否对新对象的写操作有影响
同样用上文性能对比
的数据, 分别测试对拷贝后新对象的写操作, 是否影响老对象, 结果如下
func TestShallowCopy(t *testing.T) {
r := c.ShallowCopy()
r.Int += 10000
r.String += "changed"
r.Struct.Int += 10000
r.Struct.String += "changed"
r.IntSlice[0] += 10000
r.IntSlice[1] += 10000
r.StringSlice[0] += "changed"
r.StringSlice[1] += "changed"
r.StructSlice[0].Int += 10000
r.StructSlice[0].String += "changed"
r.StructSlice[1].Int += 10000
r.StructSlice[1].String += "changed"
r.IntArray[0] += 10000
r.IntArray[1] += 10000
r.StringArray[0] += "changed"
r.StringArray[1] += "changed"
r.StructArray[0].Int += 10000
r.StructArray[0].String += "changed"
r.StructArray[1].Int += 10000
r.StructArray[1].String += "changed"
r.Map["21"] += "changed"
r.Map["23"] += "changed"
rByte, _ := json.MarshalIndent(r, "", " ")
t.Log(string(rByte))
}
结果如下可见, 确实只有Slice(无论原生类型或结构体slice), Map
有影响, 其他类型均无影响
=== RUN TestShallowCopy
main_test.go:117: {
"Int": 1,
"String": "2",
"Struct": {
"Int": 3,
"String": "4"
},
"IntSlice": [
10005,
10006
],
"StringSlice": [
"7changed",
"8changed"
],
"StructSlice": [
{
"Int": 10009,
"String": "10changed"
},
{
"Int": 10011,
"String": "12changed"
}
],
"IntArray": [
13,
14
],
"StringArray": [
"15",
"16"
],
"StructArray": [
{
"Int": 17,
"String": "18"
},
{
"Int": 19,
"String": "20"
}
],
"Map": {
"21": "22changed",
"23": "24changed"
}
}
func TestDeepCopyReflect(t *testing.T) {
r := c.DeepCopyReflect()
r.Int += 10000
r.String += "changed"
r.Struct.Int += 10000
r.Struct.String += "changed"
r.IntSlice[0] += 10000
r.IntSlice[1] += 10000
r.StringSlice[0] += "changed"
r.StringSlice[1] += "changed"
r.StructSlice[0].Int += 10000
r.StructSlice[0].String += "changed"
r.StructSlice[1].Int += 10000
r.StructSlice[1].String += "changed"
r.IntArray[0] += 10000
r.IntArray[1] += 10000
r.StringArray[0] += "changed"
r.StringArray[1] += "changed"
r.StructArray[0].Int += 10000
r.StructArray[0].String += "changed"
r.StructArray[1].Int += 10000
r.StructArray[1].String += "changed"
r.Map["21"] += "changed"
r.Map["23"] += "changed"
rByte, _ := json.MarshalIndent(c, "", " ")
t.Log(string(rByte))
}
结果如下, 确实新对象的任何改动, 都没影响老对象
=== RUN TestDeepCopyReflect
main_test.go:117: {
"Int": 1,
"String": "2",
"Struct": {
"Int": 3,
"String": "4"
},
"IntSlice": [
5,
6
],
"StringSlice": [
"7",
"8"
],
"StructSlice": [
{
"Int": 9,
"String": "10"
},
{
"Int": 11,
"String": "12"
}
],
"IntArray": [
13,
14
],
"StringArray": [
"15",
"16"
],
"StructArray": [
{
"Int": 17,
"String": "18"
},
{
"Int": 19,
"String": "20"
}
],
"Map": {
"21": "22",
"23": "24"
}
}
func TestDeepCopyJsonMarshal(t *testing.T) {
r := c.DeepCopyJsonMarshal()
r.Int += 10000
r.String += "changed"
r.Struct.Int += 10000
r.Struct.String += "changed"
r.IntSlice[0] += 10000
r.IntSlice[1] += 10000
r.StringSlice[0] += "changed"
r.StringSlice[1] += "changed"
r.StructSlice[0].Int += 10000
r.StructSlice[0].String += "changed"
r.StructSlice[1].Int += 10000
r.StructSlice[1].String += "changed"
r.IntArray[0] += 10000
r.IntArray[1] += 10000
r.StringArray[0] += "changed"
r.StringArray[1] += "changed"
r.StructArray[0].Int += 10000
r.StructArray[0].String += "changed"
r.StructArray[1].Int += 10000
r.StructArray[1].String += "changed"
r.Map["21"] += "changed"
r.Map["23"] += "changed"
rByte, _ := json.MarshalIndent(c, "", " ")
t.Log(string(rByte))
}
结果如下, 确实新对象的任何改动, 都没影响老对象
=== RUN TestDeepCopyJsonMarshal
main_test.go:117: {
"Int": 1,
"String": "2",
"Struct": {
"Int": 3,
"String": "4"
},
"IntSlice": [
5,
6
],
"StringSlice": [
"7",
"8"
],
"StructSlice": [
{
"Int": 9,
"String": "10"
},
{
"Int": 11,
"String": "12"
}
],
"IntArray": [
13,
14
],
"StringArray": [
"15",
"16"
],
"StructArray": [
{
"Int": 17,
"String": "18"
},
{
"Int": 19,
"String": "20"
}
],
"Map": {
"21": "22",
"23": "24"
}
}
func TestDeepCopyGobMarshal(t *testing.T) {
r := c.DeepCopyGobMarshal()
r.Int += 10000
r.String += "changed"
r.Struct.Int += 10000
r.Struct.String += "changed"
r.IntSlice[0] += 10000
r.IntSlice[1] += 10000
r.StringSlice[0] += "changed"
r.StringSlice[1] += "changed"
r.StructSlice[0].Int += 10000
r.StructSlice[0].String += "changed"
r.StructSlice[1].Int += 10000
r.StructSlice[1].String += "changed"
r.IntArray[0] += 10000
r.IntArray[1] += 10000
r.StringArray[0] += "changed"
r.StringArray[1] += "changed"
r.StructArray[0].Int += 10000
r.StructArray[0].String += "changed"
r.StructArray[1].Int += 10000
r.StructArray[1].String += "changed"
r.Map["21"] += "changed"
r.Map["23"] += "changed"
rByte, _ := json.MarshalIndent(c, "", " ")
t.Log(string(rByte))
}
结果如下, 确实新对象的任何改动, 都没影响老对象
=== RUN TestDeepCopyGobMarshal
main_test.go:117: {
"Int": 1,
"String": "2",
"Struct": {
"Int": 3,
"String": "4"
},
"IntSlice": [
5,
6
],
"StringSlice": [
"7",
"8"
],
"StructSlice": [
{
"Int": 9,
"String": "10"
},
{
"Int": 11,
"String": "12"
}
],
"IntArray": [
13,
14
],
"StringArray": [
"15",
"16"
],
"StructArray": [
{
"Int": 17,
"String": "18"
},
{
"Int": 19,
"String": "20"
}
],
"Map": {
"21": "22",
"23": "24"
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。