首页 > 其他分享 >go

go

时间:2023-03-24 17:02:11浏览次数:44  
标签:对象 32 fmt Pc1 go 拷贝 内存地址

 

1、深拷贝(Deep Copy)

拷贝的是数据本身,创造一个样的新对象,新创建的对象与原对象不共享内存,新创建的对象在内存中开辟一个新的内存地址,新对象值修改时不会影响原对象值。既然内存地址不同,释放内存地址时,可分别释放。

值类型的数据,默认全部都是深复制,Array、Int、String、Struct、Float,Bool。

2、浅拷贝(Shallow Copy)

拷贝的是数据地址,只复制指向的对象的指针,此时新对象和老对象指向的内存地址是一样的,新对象值修改时老对象也会变化。释放内存地址时,同时释放内存地址。

引用类型的数据,默认全部都是浅复制,Slice,Map。

 

数据结构:

//速度速值
type Speed int

//风扇转速
type FanSpeed struct {
Speed Speed
}

//售价
type Money struct {
Length float64
}

//内存数量以及大小
type Memory struct {
Count int
MemorySize []int
}

//电脑信息
type Computer struct {
SystemName string //系统名字
UseNumber int //使用次数
Memory Memory //存储
Fan map[string]FanSpeed //风扇
Money Money //售价
}

 

func ComputerStart2() {
Pc1 := Computer{
SystemName: "Windows",
UseNumber: 1000,
Memory: Memory{Count: 4, MemorySize: []int{32, 32, 32, 32}},
Fan: map[string]FanSpeed{"left": {2500}, "right": {2000}},
Money: Money{123.45},
}

//浅拷贝
Pc2:=Pc1
fmt.Printf("PcInfo Pc1:%v, Pc2:%v\n", Pc1, Pc2)

ModifyCat(Pc2)
fmt.Printf("PcInfo Pc1:%v, Pc2:%v\n", Pc1, Pc2)
}

func ModifyCat(pc Computer) {
fmt.Printf("PcInfo Pc1:%v\n", pc)
pc.SystemName ="MacOs"
pc.UseNumber =100
pc.Memory.Count =2
pc.Memory.MemorySize[0]=8
pc.Memory.MemorySize[1]=8
pc.Memory.MemorySize[2]=0
pc.Memory.MemorySize[3]=0
pc.Fan["left"]=FanSpeed{2000}
pc.Fan["right"]=FanSpeed{1500}
fmt.Printf("PcInfo Pc1:%v\n", pc)
}

 

 

输入:

PcInfo Pc1:{Windows 1000 {4 [32 32 32 32]} map[left:{2500} right:{2000}] {123.45}}, Pc2:{Windows 1000 {4 [32 32 32 32]} map[left:{2500} right:{2000}] {123.45}}
PcInfo Pc1:{Windows 1000 {4 [32 32 32 32]} map[left:{2500} right:{2000}] {123.45}}
PcInfo Pc1:{MacOs 100 {2 [8 8 0 0]} map[left:{2000} right:{1500}] {123.45}}
PcInfo Pc1:{Windows 1000 {4 [8 8 0 0]} map[left:{2000} right:{1500}] {123.45}}, Pc2:{Windows 1000 {4 [8 8 0 0]} map[left:{2000} right:{1500}] {123.45}}
这里在方法中修改PC2同样影响到了 PC1以及PC2,是因为在Golang中方法中传递的参数同样被拷贝了一份,他们修改的Slice 和 Map都是同一份地址。

参考:https://blog.csdn.net/weixin_40165163/article/details/90680466

 

地址相同,同根。

一、浅拷贝同根

func main() {
nums := [3]int{}
nums[0] = 1

fmt.Printf("nums: %v , len: %d, cap: %d\n", nums, len(nums), cap(nums))

dnums := nums[0:2]
dnums[0] = 5

fmt.Printf("nums: %v ,len: %d, cap: %d\n", nums, len(nums), cap(nums))
fmt.Printf("dnums: %v, len: %d, cap: %d\n", dnums, len(dnums), cap(dnums))
}

 

 

1、深拷贝(Deep Copy):

拷贝的是数据本身,创造一个样的新对象,新创建的对象与原对象不共享内存,新创建的对象在内存中开辟一个新的内存地址,新对象值修改时不会影响原对象值。既然内存地址不同,释放内存地址时,可分别释放。

值类型的数据,默认全部都是深复制,Array、Int、String、Struct、Float,Bool。

2、浅拷贝(Shallow Copy):

拷贝的是数据地址,只复制指向的对象的指针,此时新对象和老对象指向的内存地址是一样的,新对象值修改时老对象也会变化。释放内存地址时,同时释放内存地址。

引用类型的数据,默认全部都是浅复制,Slice,Map。

二、本质区别:

是否真正获取(复制)对象实体,而不是引用。

三、如何理解?

这里举个例子,比如P2复制了P1,修改P1属性的时候,观察P2的属性是否会产生变化

1、P2的属性变化了,说明这是浅拷贝,堆中内存还是同一个值。

p2=&p1 // 浅拷贝,p2为指针,p1和p2共用一个内存地址

2、P2的属性没变化,说明这是深拷贝,堆中内存是不同的值了。

p2=p1 // 深拷贝,生成两个内存地址

 

四、演示示例:

深拷贝示例:

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号不会变化。

浅拷贝我们用两种方式来介绍。

 

 

参考:

https://blog.csdn.net/alen_xiaoxin/article/details/124913809

https://blog.csdn.net/weixin_40165163/article/details/90680466

https://blog.csdn.net/weixin_40165163/article/details/90707593

 

标签:对象,32,fmt,Pc1,go,拷贝,内存地址
From: https://www.cnblogs.com/rebrobot/p/17252680.html

相关文章

  • Centos + Django + Nginx + uwsgi 部署项目-rpm包安装 Mysql 5
    笔者发觉下面这个方法可能有些缺陷,适合自己的就看下,如果是新开的虚拟机有可能不适用下面的方法,云服务器开的LinuxCentos系统应该可以。虚拟机安装Mysql的具体方法,可以看......
  • django -表单 forms 类的使用 - Form 和 ModelForm - 时间格式的配置
    @目录表单是搜集用户数据信息的各种表单元素的合集,其作用是实现网页上的数据交互,比如用户在网站输入数据信息,然后提交到网站服务器进行处理(如数据录入和用户登陆注册),分为......
  • (转)Beego脱坑(九)Cookie和Session
    原文:https://blog.csdn.net/yang731227/article/details/82263125title:Beego脱坑(九)Cookie和Sessiontags:go,beegoauthor:Clown95 Cookie1.Http是无状态的协议,服务......
  • go get swag找不到对应swag包
    gogetgoget命令可以借助代码管理工具通过远程拉取或更新代码包及其依赖包,并自动完成编译和安装。整个过程就像安装一个App一样简单。这个命令可以动态获取远程代码包,目......
  • 【go】snowflake和snoyflake雪花算法学习与go实现
    预备知识:MonotonicClocks,即单调时间,所谓单调,就是只会不停的往前增长,不受校时操作的影响,这个时间是自进程启动以来的秒数参考文章:https://www.simpleapples.com/2018/10/......
  • 开心档之Go 语言数据类型
    在Go编程语言中,数据类型用于声明函数和变量。数据类型的出现是为了把数据分成所需内存大小不同的数据,编程的时候需要用大数据的时候才需要申请大内存,就可以充分利用内存......
  • 开心档之Go 语言条件语句
    条件语句需要开发者通过指定一个或多个条件,并通过测试条件是否为true来决定是否执行指定语句,并在条件为false的情况在执行另外的语句。下图展示了程序语言中条件语句......
  • 开心档之Go 语言环境安装
    Go语言支持以下系统:LinuxFreeBSDMacOSX(也称为Darwin)Windows安装包下载地址为:https://golang.org/dl/。如果打不开可以使用这个地址:https://golang.google.cn/d......
  • 开心档之Go 错误处理
    Go语言通过内置的错误接口提供了非常简单的错误处理机制。error类型是一个接口类型,这是它的定义:typeerrorinterface{Error()string}我们可以在编码中通过......
  • algorithmicx(use algpseudocode as layout)学习记录
    这几天写算法作业,提供的tex文件中使用algorithmicx书写伪代码,虽然也会用algorithm2e,但技多不压身,现在就来学一学。目录概述ExampleDetails行号行注释引用Commandsifblock......