Go语言的数据类型
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
博客主页🏆看看是李XX还是李歘歘 🏆
🌺每天不定期分享一些包括但不限于计算机基础、算法、后端开发相关的知识点以及职场小菜鸡的生活。🌺
💗点关注不迷路总有一些📖知识点📖是你想要的💗
目录
本文会详细讲一下Go的理论知识包括数据类型深拷贝和浅拷贝传递
Go的数据类型
在Go中其数据类型分为基本数据类型和复合数据类型
基本数据类型
布尔型、整型、浮点型、字符型、复数型、字符串
基本数据类型全部都是值类型都是可比的但是需要注意的是在Go中字符型有两种表示byte和rune详情请参考Go语言的rune和byte的区别
复合数据类型
非引用类型数组、结构体
引用类型指针、切片、映射、通道、函数
接口类型接口
复合数据类型的可比性是否可以用==作为判断
非引用类型数组、结构体也属于值类型但是它们的可比性取决于其中变量的可比较性引用类型中指针和通道是可比的切片、映射是不可比的函数可以通过反射获取函数指针进行比较接口类型是可比较的。
函数的比较
package main import ( "fmt" "reflect" ) func lcc() { fmt.Println(1) } func lyh() { fmt.Println(1) } func main() { func1 := reflect.ValueOf(lcc) func2 := reflect.ValueOf(lcc) func3 := reflect.ValueOf(lyh) fmt.Println(func2 == func1) // true fmt.Println(func2 == func3) // false }
其中切片、map和channel的知识点可以参考
(47条消息) Go的Slice和数组_李歘歘的博客-CSDN博客_go slice 元素个数
深拷贝和浅拷贝
概念
深拷贝拷贝的是数据本身创造一个样的新对象新创建的对象与原对象不共享内存新创建的对象在内存中开辟一个新的内存空间新对象值修改时不会影响原对象值。既然内存地址不同释放内存地址时分别释放。
值类型的数据基本数据类型+复合数据类型的非引用类型默认全部采用深拷贝。
浅拷贝拷贝的是数据地址只复制指向的对象的指针此时新对象和老对象指向的内存地址是一样的新对象值修改时老对象也会变化。释放内存地址时同时释放内存地址。
引用类型的数据默认全部采用浅拷贝。
引用类型想实现深拷贝就不能直接 := 而是要先 new 再赋值。slice也可以使用copy函数进行深拷贝。
深拷贝会拷贝数据两变量存储地址不同拷贝结束互不影响。浅拷贝只会拷贝内存的地址即使拷贝结束还是互相影响
代码解释
深拷贝和浅拷贝
package main
import "fmt"
func main() {
// slice是浅拷贝改变了a的值b也会变化而且内存空间是同一个
a := []int{1}
b := []int{2}
fmt.Println(a[0], &a[0])
fmt.Println(b[0], &b[0])
b = a
a[0] = 3
fmt.Println(a[0], &a[0])
fmt.Println(b[0], &b[0])
fmt.Println("----------------------------")
// array是深拷贝改变了c的值d的值不变而且内存空间是两个
c := [1]int{1}
d := [1]int{2}
fmt.Println(c[0], &c[0])
fmt.Println(d[0], &d[0])
d = c
c[0] = 3
fmt.Println(c[0], &c[0])
fmt.Println(d[0], &d[0])
}
slice实现深拷贝
package main
import "fmt"
func main() {
// slice的深拷贝实现----copy函数改变了c的值d的值不变而且内存空间是两个
a := []int{1}
b := []int{2}
fmt.Println(a[0], &a[0])
fmt.Println(b[0], &b[0])
copy(a, b) // copy是深拷贝
a[0] = 3
fmt.Println(a[0], &a[0])
fmt.Println(b[0], &b[0])
fmt.Println("----------------------------")
}
传递
官方给的文档说明go中的所有传递都是值传递都是一个副本一个拷贝。
在 go 语言中 值类型赋值都是深拷贝 引用类型一般都是浅拷贝。但是实际传递过程中值类型会生成一个副本进行传递引用类型会生成一个指针副本进行传递所以在go中的所有传递都是值传递。
有的同学可能不懂为啥引用类型也是值传递?
引用类型的时候他们的结构体中并没有直接保存数据而是保存了指向数据的指针那么在传递时候就拷贝了一份它们自己的一份结构体包括只想地址的指针结构体里面具体保存的指针指向的地址还是同一份没有变化的。所以这也就说明函数中为什么可以改变引用类型变量的值了因为底层指针指向的地址是同一个。
func lcc(a int) {
fmt.Println(&a)
}
func lyh(a []int) {
fmt.Println(&a[0])
}
func main() {
a := 1
fmt.Println(&a)
lcc(a)//值类型复制了一个新的值所以是一个新的地址
b := []int{1}
fmt.Println(&b[0])
lyh(b)//引用类型复制了一个指向该地址的指针所以说地址不变
}