机器级程序将内存视为一个非常大的字节数组,称为虚拟内存(virtual memory)。内存的每个字节都由一个唯一的数字来标识,称为它的地址(address),所有可能地址的集合就称为虚拟地址空间(virtual memory space)。
所以,从内存管理上看,编程语言中的数据类型表示的是存储的何种类型的数据,就是一个类型占用的内存大小。也就是说,数据类型的出现是为了把数据分成所需内存大小不同的数据
在程序中,我们通过指定其类型,能实现以特定字节数为单位来进行读写。
Go语言提供了丰富的数据组织形式,其数据类型可以分为四类:基础类型、复合类型、引用类型和接口类型。这里,我们将探索最基础的一类—基础数据类型。
总的来说,基本的数据类型有如下几种:
数字类型
int8int16int32int64uint8uint16uint32uint64
示例:
intint64int
1 Byte(字节) = 8 b(bit)
1 KB = 1024 B
1 MB = 1024 KB
1 GB = 1024 MB
int
无符号数的编码
假设有一个整数数据类型有
w
w
w 位,我们将位向量写成
x
⃗
\vec{x}
x
,表示整个向量,或写成
[
x
w
−
1
,
x
w
−
2
,
.
.
.
,
x
0
]
[x_{w-1},x_{w-2},...,x_0]
[xw−1,xw−2,...,x0] ,表示向量中的每一位。把
x
⃗
\vec{x}
x
看成一个二进制表示的数,就获得了
x
⃗
\vec{x}
x
的无符号表示。由于是无符号,则不需要考虑负数的情况,于是有,对二进制向量:
x
⃗
=
[
x
w
−
1
,
x
w
−
2
,
.
.
.
,
x
0
]
\vec{x} = [x_{w-1},x_{w-2},...,x_0]
x
=[xw−1,xw−2,...,x0]
有:
B
2
T
w
(
x
⃗
)
=
∑
i
=
0
w
−
1
x
i
2
i
B2T_w(\vec x) = \sum_{i=0}^{w-1} x_{i}2^i
B2Tw(x
)=i=0∑w−1xi2i
举个例子:
B
2
T
4
(
[
0101
]
)
=
0
⋅
2
3
+
1
⋅
2
2
+
0
⋅
2
1
+
1
⋅
2
0
=
0
+
4
+
0
+
1
=
5
B
2
T
4
(
[
1011
]
)
=
1
⋅
2
3
+
0
⋅
2
2
+
1
⋅
2
1
+
1
⋅
2
0
=
8
+
0
+
2
+
1
=
11
\begin{aligned} B2T_4([0101]) &= 0\cdot2^3 + 1 \cdot2^2 + 0\cdot2^1 + 1\cdot2^0 = 0 + 4 + 0 + 1 = 5 \\ B2T_4([1011]) &= 1\cdot2^3 + 0 \cdot2^2 + 1\cdot2^1 + 1\cdot2^0 = 8 + 0 + 2 + 1 = 11 \end{aligned}
B2T4([0101])B2T4([1011])=0⋅23+1⋅22+0⋅21+1⋅20=0+4+0+1=5=1⋅23+0⋅22+1⋅21+1⋅20=8+0+2+1=11
补码编码
在许多应用中,我们希望表示负数值。最常见的有符号的计算表示方式就是 补码 形式。在这个定义中,将字的最高位解释为 负权(negative weight):
对二进制向量:
x
⃗
=
[
x
w
−
1
,
x
w
−
2
,
.
.
.
,
x
0
]
\vec{x} = [x_{w-1},x_{w-2},...,x_0]
x
=[xw−1,xw−2,...,x0]
有:
B
2
T
w
(
x
⃗
)
=
−
x
w
−
1
2
w
−
1
+
∑
i
=
0
w
−
2
x
i
2
i
B2T_w(\vec x) = -x_{w-1}2^{w-1} + \sum_{i=0}^{w-2} x_{i}2^i
B2Tw(x
)=−xw−12w−1+i=0∑w−2xi2i
其中,最高有效位
w
−
1
w-1
w−1 也称为 符号位,当值为 1 时,表示负值,当值为 0 时,表示非负。我们可以看看例子:
B
2
T
4
(
[
0101
]
)
=
−
0
⋅
2
3
+
1
⋅
2
2
+
0
⋅
2
1
+
1
⋅
2
0
=
0
+
4
+
0
+
1
=
5
B
2
T
4
(
[
1011
]
)
=
−
1
⋅
2
3
+
0
⋅
2
2
+
1
⋅
2
1
+
1
⋅
2
0
=
−
8
+
0
+
2
+
1
=
−
5
\begin{aligned} B2T_4([0101]) &= -0\cdot2^3 + 1 \cdot2^2 + 0\cdot2^1 + 1\cdot2^0 = 0 + 4 + 0 + 1 = 5 \\ B2T_4([1011]) &= -1\cdot2^3 + 0 \cdot2^2 + 1\cdot2^1 + 1\cdot2^0 = -8 + 0 + 2 + 1 = -5 \end{aligned}
B2T4([0101])B2T4([1011])=−0⋅23+1⋅22+0⋅21+1⋅20=0+4+0+1=5=−1⋅23+0⋅22+1⋅21+1⋅20=−8+0+2+1=−5
取值范围
int8
int8 占有 1 Byte,在二进制中是 8 bit
由于是有符号整数,在二进制中,在高位使用 0 或 1 表示正负号: 0--正号,1--负号
于是,最大数为:0 1 1 1 1 1 1 1
根据上面的补码知识,我们可以计算出:
B2T([01111111]) = -0*2^7 + 1*2^6 + 1*2^5 + ... + 1*2^0 = 127
B2T([10000000]) = -1*2^7 + 0*2^6 + 0*2^5 + ... + 0*2^0 = -128
验证如下:
func main() {
var x int8 = 1
fmt.Printf("占用字节: %d\n", unsafe.Sizeof(x)) //占用字节: 1
fmt.Printf("最小值: %d,最大值: %d\n", math.MinInt8, math.MaxInt8) //最小值: -128,最大值: 127
}
其他的数值也如是计算即可:
go 数据类型 | 最小值 | 最大值 |
---|---|---|
int/int64 | -9223372036854775808 | 9223372036854775807 |
int8 | -128 | 127 |
int16 | -32768 | 32767 |
int32 | -2147483648 | 2147483647 |
uint8 | 0 | 255 |
uint16 | 0 | 65535 |
uint32 | 0 | 4294967295 |
uint64 | 0 | 18446744073709551615 |
浮点数
关于浮点数,本文还没有进行深入的探究,可以参考其他人的文章描述:Golang 笔记之深入浮点数
探究其取值范围:
func main() {
fmt.Println("双精度浮点数表示正数的最小值是:", math.SmallestNonzeroFloat64) //5e-324
fmt.Println("双精度浮点数表示正数的最大值是:", math.MaxFloat64) //1.7976931348623157e+308
}
float64float32
字符类型
string
stringbyterune
我们先看下面一段代码:
func main() {
var str string = "hello, world"
var strByte = [...]byte{
'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd',
}
var strRune = [...]rune{
'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd',
}
fmt.Println([]byte(str))
fmt.Println(strByte)
fmt.Println(strRune) //三者相等
// [104 101 108 108 111 44 32 119 111 114 108 100],这是Unicode编码10进制的表示
}
string
布尔型
truefalse
使用代码:
byte
虚数
Go语言提供了两种精度的复数类型:complex64s和complex128,分别对应float32和float64两种浮点数精度。内置的complex函数用于构建复数,内建的real和imag函数分别返回复数的实部和虚部: