数据类型与内存分配
数据类型
- 基本数据类型
- 布尔(bool)
- 数值类型:
- 整形(int)
- 浮点型(float)
- 字符串类型 (string)
- 派生数据类型
- 指针
- 数组(Array)
- 结构体(struct)
- 管道(channel)
- 切片(slice)
- 接口(interface)
- 映射(Map)
- 函数(func)
内存分配方式
数据类型的分类
值类型: 布尔类型、数值类型、字符串类型、数组类型、结构体类型
引用类型:指针、通道、切片、接口、映射、函数
内存空间分为栈内存和堆内存,值类型一般由内存中的栈内存进行空间分配,
值类型的内存分配
声明的本质是命令计算机在内存上开辟一块内存空间用来存放我们的数据,内存地址用来标记这块空间,为了方便我们编程,现代计算机语言中通常使用标识符来代替内存地址
// 标识符 地址 栈内存
var x:int = 1 // X 0X0001 1
var y:int = x // Y 0X0002 1 <= x 将 x 的值拷贝过来这里实际上是开辟了两块不同的内存空间,当我们改变 x 的值的时候 y 并不会随之改变
// 标识符 地址 栈内存
var x:int = 1 // X 0X0001 1 <= 2 这里的值被下面改变了
var y:int = x // Y 0X0002 1 这里的值还是1
x = 2 // 它会去寻找 标识符 x 对于的地址所指向的内存空间,并改变其中的值引用类型的内存分配
在引用类型中通常将数据存储在堆内存里,在标识符对于的栈内存空间中实际上存储的是堆内存的内存地址
// 标识符 地址 栈内存 内存地址 堆内存
x = [1, 2, 3] // x 0x00001 0x10001 0x10001 [1,2,3]
y = x // y 0x00002 0x10001这个时候 y 与 x 是指向的同一块堆内存,所以当我改变 x 中的一个元素的值时,y 也会跟着一起被改变
引用类型对于内存空间的分配是动态的
在golang的设计理念中数组和结构体的长度是固定的,所它们是值类型而不是引用类型,我们在定义他们的时候要指定长度和存储的元素的数据类型
指针
指针的本质就是内存地址, 我们可以使用&+标识符的形式获取一个这个标识符所代表的指针,也可以使用*前缀来找到一个指针所指向的内存空间中的值
// 标识符 地址 栈内存
var x int = 1 // x 0x00001 1
var ptr *int = &x // ptr 0x00002 0x00001 将 x 这个标识符所代表的内存地址放到栈内存里
var y int = *ptr // y 0x00003 1 将 0x00001 这个指针指向的内存中的值放到这里指针本身是没有类型的, 它是一段16进制的地址索引
var ptr *int = &x这里的 int 表示这个指针所指向内存空间中的值的内型,比如当 x 为一个浮点型时
var ptr *float64 = &x数值类型的存储空间和取值范围
整型
| 名称 | 字节数 | 存储位数 | 取值范围 |
|---|---|---|---|
| int | 4/8 | 32/64 | -231 ~ 231-1 / -264 ~ 264-1 |
| int8 | 1 | 8 | -27 ~ 27-1 (-128 ~ 127) |
| int16 | 2 | 16 | -215 ~ 215-1 (-32768 ~ 32767) |
| int32 | 4 | 32 | -231 ~ 231-1 (-2147483648 ~ 2147483647) |
| int64 | 8 | 64 | -263 ~ 263-1 |
| uint | 4/8 | 32/64 | 0 ~ 232-1 / 0 ~ 264-1 |
| uint8 | 1 | 8 | 0 ~ 28-1 (0 ~ 255) |
| uint16 | 2 | 16 | 0 ~ 216-1 (0 ~ 65535) |
| uint32 | 4 | 32 | 0 ~ 232-1 (0 ~ 4294967295) |
| uint64 | 8 | 64 | 0 ~ 264-1 (0 ~ 18446744073709551615) |
浮点型
| 名称 | 字节数 | 存储位数 | 负数的取值范围 | 正数的取值范围 |
|---|---|---|---|---|
| float32 | 4 | 32 | -3.4E38 ~ -1.4E-45 | 1.4E-45 ~ 3.4E38 |
| float64 | 8 | 64 | -1.7E308 ~ -4.9E-324 | 4.9E-324 ~ 1.7E308 |
复数
复数由两个浮点数组成,分别是实部和虚部
| 名称 | 字节数 | 存储位数 | 取值范围 |
|---|---|---|---|
| complex64 | 8 | 64 | (-1.18E4932 ~ -4.9E-324i) ~ (1.18E4932 ~ 4.9E-324i) |
| complex128 | 16 | 128 | (-1.18E4932 ~ -4.9E-324i) ~ (1.18E4932 ~ 4.9E-324i) |
字符类型
单个字符(char)
在 golang 中用单引好表示单个字符
var ch = 'a'ASCLII字符
使用byte来表示ASCLII码中的字符,它实际上是一个unint8类型,也就是一个字节,长度为8位,取值范围为0 ~ 255
var ch byte = 'a'
fmt.Println(ch) // 97 <= 'a' 的ASCLII码
var ch byte = 97
fmt.Println("%c" ch) //Unicode字符
使用rune来表示Unicode中的字符,它实际上是一个int32类型,也就是4个字节,长度为32位,取值范围为-231 ~ 231-1
var ch rune = '你'
fmt.Println(ch) // 20320 <= '你' 的Unicode码
var ch rune = 20320
fmt.Println("%c" ch) // 你字符串
字符串是由字符组成的合集,在golang使用双引号来表示字符串
var str string = "hello world"
var str2 string = 'hello world' // 编译错误字符串的长度可以通过len()函数来获取
var str string = "hello world"
fmt.Println(len(str)) // 11字符串的拼接可以使用+符号
var str1 string = "hello world"
var str2 string = "NAN"
var str3 string = str1 + ", " + str2在golang中的中文字符占用 3 个字节,英文字符占用 1 个字节
var strA string = "I"
fmt.Println(len(strA)) // 1
var strB string = "我"
fmt.Println(len(strB)) // 3