開発では、ある変数を別の変数にコピーすることが多いため、このプロセスは浅いコピーになる可能性があるため、本日は、これら2つのコピーの違いと具体的な違いを区別できるようにします。
1.コンセプト
1.ディープコピー:
コピーされるのはデータ自体であり、新しい種類のオブジェクトを作成します。新しく作成されたオブジェクトは、元のオブジェクトとメモリを共有しません。新しく作成されたオブジェクトは、メモリ内の新しいメモリアドレスを開き、新しいオブジェクトの値は変更時に元のオブジェクトの値に影響しません。メモリアドレスが異なるため、メモリアドレスを解放する際に、個別に解放できます。
デフォルトでは、値タイプのすべてのデータはディープコピー、配列、整数、文字列、構造体、浮動小数点数、ブール値です。
2.浅いコピー:
データアドレスがコピーされ、ポイントされたオブジェクトのポインタのみがコピーされます。このとき、新しいオブジェクトと古いオブジェクトが指すメモリアドレスは同じであり、新しいオブジェクトの値が変更されると、古いオブジェクトも変更されます。メモリアドレスが解放されると、同時にメモリアドレスも解放されます。
参照タイプのデータは、すべてデフォルトで浅いコピー、スライス、マップです。
第二に、本質的な違い:
参照ではなく、実際にオブジェクトエンティティを取得(コピー)するかどうか。
3.理解するには?
たとえば、P2がP1をコピーしてP1属性を変更する場合、P2の属性が変更されるかどうかを確認します。
1. P2のプロパティが変更されました。これは浅いコピーであり、ヒープ内のメモリは同じ値であることを示しています。
p2=&p1 // 浅拷贝,p2为指针,p1和p2共用一个内存地址
2. P2のプロパティは変更されていません。これはディープコピーであり、ヒープ内のメモリが異なる値であることを示しています。
p2=p1 // 深拷贝,生成两个内存地址
4.デモの例:
ディープコピーの例:
package main
import (
"fmt"
)
// 定义一个Robot结构体
type Robot struct {
Name string
Color string
Model string
}
func main() {
fmt.Println("深拷贝 内容一样,改变其中一个对象的值时,另一个不会变化。")
robot1 := Robot{
Name: "小白-X型-V1.0",
Color: "白色",
Model: "小型",
}
robot2 := robot1
fmt.Printf("Robot 1:%s\t内存地址:%p \n", robot1, &robot1)
fmt.Printf("Robot 2:%s\t内存地址:%p \n", robot2, &robot2)
fmt.Println("修改Robot1的Name属性值")
robot1.Name = "小白-X型-V1.1"
fmt.Printf("Robot 1:%s\t内存地址:%p \n", robot1, &robot1)
fmt.Printf("Robot 2:%s\t内存地址:%p \n", robot2, &robot2)
}
演算結果:
深拷贝 内容一样,改变其中一个对象的值时,另一个不会变化。
Robot 1:{小白-X型-V1.0 白色 小型} 内存地址:0xc000072330
Robot 2:{小白-X型-V1.0 白色 小型} 内存地址:0xc000072360
修改Robot1的Name属性值
Robot 1:{小白-X型-V1.1 白色 小型} 内存地址:0xc000072330
Robot 2:{小白-X型-V1.0 白色 小型} 内存地址:0xc000072360
ディープコピーでは、Robot1のアドレスとRobot2のメモリアドレスが異なっていることがわかります。Robot1のNameプロパティを変更しても、Robot2は変更されません。
浅いコピーを2つの方法で紹介します。
浅いコピーの例1:
package main
import (
"fmt"
)
// 定义一个Robot结构体
type Robot struct {
Name string
Color string
Model string
}
func main() {
fmt.Println("浅拷贝 内容和内存地址一样,改变其中一个对象的值时,另一个同时变化。")
robot1 := Robot{
Name: "小白-X型-V1.0",
Color: "白色",
Model: "小型",
}
robot2 := &robot1
fmt.Printf("Robot 1:%s\t内存地址:%p \n", robot1, &robot1)
fmt.Printf("Robot 2:%s\t内存地址:%p \n", robot2, robot2)
fmt.Println("在这里面修改Robot1的Name和Color属性")
robot1.Name = "小黑-X型-V1.1"
robot1.Color = "黑色"
fmt.Printf("Robot 1:%s\t内存地址:%p \n", robot1, &robot1)
fmt.Printf("Robot 2:%s\t内存地址:%p \n", robot2, robot2)
}
演算結果1:
浅拷贝 内容和内存地址一样,改变其中一个对象的值时,另一个同时变化。
Robot 1:{小白-X型-V1.0 白色 小型} 内存地址:0xc000062330
Robot 2:&{小白-X型-V1.0 白色 小型} 内存地址:0xc000062330
在这里面修改Robot1的Name和Color属性
Robot 1:{小黑-X型-V1.1 黑色 小型} 内存地址:0xc000062330
Robot 2:&{小黑-X型-V1.1 黑色 小型} 内存地址:0xc000062330
浅いコピーでは、Robot1とRobot2のメモリアドレスが同じであることがわかります。一方のオブジェクトの属性が変更されると、もう一方のオブジェクトも変更されます。
浅いコピーの例2:
package main
import (
"fmt"
)
// 定义一个Robot结构体
type Robot struct {
Name string
Color string
Model string
}
func main() {
fmt.Println("浅拷贝 使用new方式")
robot1 := new(Robot)
robot1.Name = "小白-X型-V1.0"
robot1.Color = "白色"
robot1.Model = "小型"
robot2 := robot1
fmt.Printf("Robot 1:%s\t内存地址:%p \n", robot1, robot1)
fmt.Printf("Robot 2:%s\t内存地址:%p \n", robot2, robot2)
fmt.Println("在这里面修改Robot1的Name和Color属性")
robot1.Name = "小蓝-X型-V1.2"
robot1.Color = "蓝色"
fmt.Printf("Robot 1:%s\t内存地址:%p \n", robot1, robot1)
fmt.Printf("Robot 2:%s\t内存地址:%p \n", robot2, robot2)
}
演算結果:
浅拷贝 使用new方式
Robot 1:&{小白-X型-V1.0 白色 小型} 内存地址:0xc000068330
Robot 2:&{小白-X型-V1.0 白色 小型} 内存地址:0xc000068330
在这里面修改Robot1的Name和Color属性
Robot 1:&{小黑-X型-V1.2 黑色 小型} 内存地址:0xc000068330
Robot 2:&{小黑-X型-V1.2 黑色 小型} 内存地址:0xc000068330
新しい操作robot2:= robot1はディープコピーのように見えますが、実際には浅いコピーであり、robot2とrobot1の2つのポインタは同じメモリアドレスを共有しています。