基本数据类型
程序实体与关键字
- 任何Go语言源码文件都由若干个程序实体组成的。在Go语言中,变量、常量、函数、结构体和接口被统称为“程序实体”,而它们的名字被统称为“标识符”。
- 标识符可以是任何Unicode编码可以表示的字母字符、数字以及下划线“_”。不过,首字母不能是数字或下划线。
- 注意:在Go语言中,我们对程序实体的访问权限控制只能通过它们的名字来实现。名字首字母为大写的程序实体可以被任何代码包中的代码访问到。而名字首字母为小写的程序实体则只能被同一个代码包中的代码所访问。
- Go语言还规定了一些特定的字符序列。它们被称为“关键字”。编程人员不能把关键字作为标识符。Go语言的关键字如下表:
用途 | 关键字 |
---|---|
程序声明 | import package |
程序实体声明和定义 | chan const func interface map struct type var |
程序流程控制 | go select break case continue default derfer else fallthrough for goto if range return switch |
变量和常量
我们在这里需要优先说明的是用于声明变量的关键字var,以及用于声明常量的关键字const。要知道,绝大多数的数据类型的值都可以被赋给一个变量,包括函数。而常量则不同,它只能被赋予基本数据类型的值本身。
变量和常量在声明方式方面也有所不同。我们可以在声明一个变量的时候直接为它赋值,也可以只声明不赋值。变量的声明并赋值方式如下:
普通赋值,由关键字var、变量名称、变量类型、特殊标记=,以及相应的值组成。 若只声明不赋值,则去除最后两个组成部分即可。
或
平行赋值
或
上述这三种变量声明的方式,也适用于常量。但是要注意,对于常量不能出现只声明不赋值的情况。
范例:
整数类型的命名和宽度
Go语言的整数类型一共有10个。
其中计算架构相关的整数类型有两个,即:有符号的整数类型 int 和无符号的整数类型 uint。
顺便提一下,有符号的整数类型会使用最高位的比特(bit)表示整数的正负。显然,这会对它能表示的整数的范围有一定的损耗(使其缩小)。而无符号的整数类型会使用所有的比特位来表示数值。如此类型的值均为正数。这也是用“无符号的”来形容它们的原因。
言归正传,为什么说这两个整数类型是计算架构相关的呢?这是因为,在不同的计算架构的计算机之上,它们体现的宽度是不同的。宽度即指存储一个某类型的值所需要的空间。空间的单位可以是比特,也可以是字节(byte)。请看下表。
数据类型 | 计算架构 | 类型宽度(比特) | 类型宽度(字节) |
---|---|---|---|
int |
32位 | 32 | 4 |
int |
64位 | 64 | 8 |
uint |
32位 | 32 | 4 |
uint |
64位 | 64 | 8 |
以上为对应关系
除了这两个计算架构相关的整数类型之外,还有8个可以显式表达自身宽度的整数类型。如下表所示。
数据类型 | 有符号 | 类型宽度(比特) |
---|---|---|
int8 |
是 | 8 |
int16 |
是 | 16 |
int32 |
是 | 32 |
int64 |
是 | 64 |
uint8 |
否 | 8 |
uint16 |
否 | 16 |
uint32 |
否 | 32 |
uint64 |
否 | 64 |
可以看到,这8个整数类型的宽度已经表现在它们的名称中了。
范例:
整数类型的表示法
我们已经知道了每个整数类型的宽度,那么它们的宽度意味着什么呢?下面这张表已有所描述。
类型宽度(比特) | 数值范围(有符号整数) | 数值范围(无符号整数) |
---|---|---|
8 |
-128 ~ 127 |
0 ~ 255 |
16 |
-32768 ~ 32767 |
0 ~ 65535 |
32 |
约 -21.47 ~ 21.47亿 |
约0 ~ 42.94亿 |
64 |
约 -922亿亿 ~ 922亿亿 |
约0 ~ 1844亿亿 |
如上所示,类型int8
的数值表示范围为[-128,127],而类型uint16
的数值表示范围为[0,65535],等等。
以我们的常识知道,在数学中整数一般是以10进制来表示的,而在计算机中整数则必是以2进制来表示和存储的。当然,在计算机科学领域,整数的表示形式还包括了8进制和16进制。下面我们就来说说怎样这几种表示法在Go语言中表示整数。
最显而易见的是10进制表示法。如果我们要在声明一个名为num1的int类型变量时给它赋予12这个值,那么这样书写即可:
这是最容易被我们理解的方式了。不过,如果我们要分别以8进制和16进制为变量num1赋值,那么需要:
范例:
浮点数类型
浮点数类型有两个,即float32
和float64
。你可能已经想到,存储这两个类型的值的空间分别需要4个字节和8个字节。
浮点数类型的值一般由整数部分、小数点“.”和小数部分组成。其中,整数部分和小数部分均由10进制表示法表示。不过还有另一种表示方法。那就是在其中加入指数部分。指数部分由“E”或“e”以及一个带正负号的10进制数组成。比如,3.7E-2
表示浮点数0.037
。又比如,3.7E+1
表示浮点数37
。
有时候,浮点数类型值的表示也可以被简化。比如,37.0
可以被简化为37
。又比如,0.037
可以被简化为.037
。
有一点需要注意,在Go语言里,浮点数的相关部分只能由10进制表示法表示,而不能由8进制表示法或16进制表示法表示。比如,03.7
表示的一定是浮点数3.7
。
范例:
复数类型
复数类型同样有两个,即complex64
和complex128
。存储这两个类型的值的空间分别需要8个字节和16个字节。实际上,complex64
类型的值会由两个float32
类型的值分别表示复数的实数部分和虚数部分。而complex128
类型的值会由两个float64
类型的值分别表示复数的实数部分和虚数部分。
复数类型的值一般由浮点数表示的实数部分、加号“+”、浮点数表示的虚数部分,以及小写字母“i”组成。比如,3.7E+1 + 5.98E-2i
。正因为复数类型的值由两个浮点数类型值组成,所以其表示法的规则自然需遵从浮点数类型的值表示法的相关规则。
范例:
byte 与 rune
byte
与rune
类型有一个共性,即:它们都属于别名类型。byte
是uint8
的别名类型,而rune
则是int32
的别名类型。
byte
类型的值需用8个比特位表示,其表示法与uint8
类型无异。因此我们就不再这里赘述了。我们下面重点说说rune
类型。
一个rune
类型的值即可表示一个Unicode字符。Unicode是一个可以表示世界范围内的绝大部分字符的编码规范。关于它的详细信息,大家可以参看其官网(http://unicode.org/
)上的文档,或在Google上搜索。用于代表Unicode字符的编码值也被称为Unicode代码点。一个Unicode代码点通常由“U+”和一个以十六进制表示法表示的整数表示。例如,英文字母“A”的Unicode代码点为“U+0041”。
rune
类型的值需要由单引号“'”包裹。例如,'A'
或'郝'
。这种表示方法一目了然。不过,我们还可以用另外几种形式表示rune
类型值。请看下表。
示例 | 备注 | 关键字 |
---|---|---|
直接使用Unicode字符 | '郝'表示中文字符“郝” | 只能表示Unicode支持的字符 |
“\x”加两个十六进制数 | '\x41' 表示英文字母 'A' | 只能表示ASCII支持的字符 |
“\”加三位八进制数 | '\101\' 表示英文字母 'A' | 只能表示编码值在 [0, 255] 内的字符 |
“\u”加四位十六进制数 | '\u90DD' 表示 “郝” | 只能表示编码值在 [0, 65535] 内的字符 |
“\U”加四位十六进制数 | '\U000090DD' 表示 “郝” | 可以用于表示任何Unicode字符 |
大家需要根据实际情况选用上述表示法。在一般情况下,第一种表示法更为通用。因为它是最直观的。不过,在以其他几种方法表示的内容出现在屏幕上的时候,大家也要明白其含义。
另外,在rune
类型值的表示中支持几种特殊的字符序列,即:转义符。它们由“\”和一个单个英文字符组成。如下表所示。
转义符 | Unicode代码点 | 说明 |
---|---|---|
\a | U+0007 | 告警铃声或蜂鸣声 |
\b | U+0008 | 退格符 |
\f | U+000C | 换页符 |
\n | U+000A | 换行符 |
\r | U+000D | 回车符 |
\t | U+0009 | 水平制表符 |
\v | U+000b | 垂直制表符 |
\ | U+005c | 反斜杠 |
\' | U+0027 | 单引号。仅在rune值中有效 |
'' | U+0022 | 双引号。仅在string值中有效 |
范例:
相关Unicode编码表(如:http://unicode-table.com/cn/)。
字符串类型
顾名思义,一个字符串类型的值可以代表一个字符序列。这些字符必须是被Unicode编码规范支持的。虽然从表象上来说是字符序列,但是在底层,一个字符串值却是由若干个字节来表现和存储的。一个字符串(也可以说字符序列)会被Go语言用Unicode编码规范中的UTF-8编码格式编码为字节数组。
注意,我们在一个字符串值或者一个字符串类型的变量之上应用Go语言的内置函数len将会得到代表它的那个字节数组的长度。这可能与我们看到的表象是不同的。
字符串的表示法有两种,即:原生表示法和解释型表示法。若用原生表示法,需用反引号“`”把字符序列包裹起来。若用解释型表示法,则需用双引号“"”包裹字符序列。
二者的区别是,前者表示的值是所见即所得的(除了回车符)。在那对反引号之间的内容就是该字符串值本身。而后者所表示的值中的转义符会起作用并在程序编译期间被转义。所以,如此表示的字符串值的实际值可能会与我们看到的表象不相同。
最后要注意,字符串值是不可变的。也就是说,我们一旦创建了一个此类型的值,就不可能再对它本身做任何修改。
范例: