第四章(下):基本数据类型
常量
常量使用关键字 const
定义,用于存储不会改变的数据。
存储在常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。
1 | const Pi = 3.14 |
常量的值必须是能够在编译时就能够确定的。
因为在编译期间自定义函数均属于未知,因此无法用于常量的赋值,但内置函数可以使用,如:len()。
1 | const Ln2 = 0.693147180559945309417232121458\ |
反斜杠 \
可以在常量表达式中作为多行的连接符使用。
常量并行赋值
1 | const beef,two,c = "eat",2,"vag" |
iota
可以被用作枚举值:
1 | const ( |
简单地讲,每遇到一次 const 关键字,iota 就重置为 0。.
变量
声明变量的一般形式是使用 var
关键字:var identifier type
。
1 | var a int |
变量的命名规则遵循骆驼命名法。
全局变量希望能够被外部包所使用,则需要将首个单词的首字母也大写。
变量可以编译期间就被赋值,赋值给变量使用运算符等号 =
,可以在运行时对变量进行赋值操作。
1 | var a int |
声明与赋值(初始化)语句也可以组合起来。
1 | var a int = 15 |
自动类型推断
1 | var a = 15 |
在函数体内声明局部变量时,应使用简短声明语法 :=
,例如:
1 | a := 1 |
实例:
1 | package main |
值类型和引用类型
int、float、bool 和 string 这些基本类型都属于值类型,使用这些类型的变量直接指向存在内存中的值。
数组和结构体这些复合类型是值类型。
指针、切片、映射和通道是引用类型。被引用的变量会存储在堆中,以便进行垃圾回收,且比栈拥有更大的内存空间。
函数 fmt.Sprintf
与 Printf
的作用是完全相同的,不过前者将格式化后的字符串以返回值的形式返回给调用者。
在相同的代码块中,我们不可以再次对于相同名称的变量使用初始化声明,例如:a := 20
就是不被允许的。
1 | a, b, c := 5, 7, "abc" |
交换两个变量的值,则可以简单地使用 a, b = b, a
。
init函数
变量除了可以在全局声明中初始化,也可以在 init 函数中初始化。
每个源文件都只能包含一个 init 函数。初始化总是以单线程执行,并且按照包的依赖关系顺序执行。
用途是在开始执行程序之前对数据进行检验或修复,以保证程序状态的正确性。
1 | package trans |
1 | package main |
init 函数也经常被用在当一个程序开始之前调用后台执行的 goroutine。
1 | func init() { |
基本类型与运算符
bool类型
只有两个类型相同的值才可以进行比较,如果值的类型是接口,它们也必须都实现了相同的接口。
布尔型的常量和变量也可以通过和逻辑运算符(非 !
、和 &&
、或 ||
)结合来产生另外一个布尔值。
!
非运算符用于取得和布尔值相反的结果。
&&
两边的值都为 true 的时候,结果才是 true。
||
两边的值都为 false 的时候,结果才是 false。
在格式化输出时,你可以使用 %t
来表示你要输出的值为布尔型。
数字类型
Go 语言支持整型和浮点型数字,并且原生支持复数,其中位的运算采用补码。
Go 也有基于架构的类型,例如:int、uint 和 uintptr。
这些类型的长度都是根据运行程序所在的操作系统类型所决定的:
int
和uint
在 32 位操作系统上,它们均使用 32 位(4 个字节),在 64 位操作系统上,它们均使用 64 位(8 个字节)。uintptr
的长度被设定为足够存放一个指针即可。
Go 语言中没有 float 类型。(Go语言中只有 float32 和 float64)没有double类型。
int 型是计算最快的一种类型。
float32 精确到小数点后 7 位,float64 精确到小数点后 15 位。
尽可能地使用 float64,因为 math
包中所有有关数学运算的函数都会要求接收这个类型。
前缀 0 来表示 8 进制数(如:077),增加前缀 0x 来表示 16 进制数(如:0xFF),以及使用 e 来表示 10 的连乘(如: 1e3 = 1000,或者 6.022e23 = 6.022 x 1e23)。
可以使用 a := uint64(0)
来同时完成类型转换和赋值操作,这样 a 的类型就是 uint64。
Go 中不允许不同类型之间的混合使用,但是对于常量的类型限制非常少,因此允许常量之间的混合使用:
1 | package main |
格式化说明符
%d
用于格式化整数(%x
和 %X
用于格式化 16 进制表示的数字),%g
用于格式化浮点型(%f
输出浮点数,%e
输出科学计数表示法),%0nd
用于规定输出长度为n的整数,其中开头的数字 0 是必须的。
%n.mg
用于表示数字 n 并精确到小数点后 m 位,除了使用 g 之外,还可以使用 e 或者 f,例如:使用格式化字符串 %5.2e
来输出 3.4 的结果为 3.40e+00
。
/
对于整数运算而言,结果依旧为整数,例如:9 / 4 -> 2
。
取余运算符只能作用于整数:9 % 4 -> 1
。
对于整数和浮点数,你可以使用一元运算符 ++
(递增)和 --
(递减),但只能用于后缀。
++
和 --
的只能作为语句,而非表达式,因此 n = i++
这种写法是无效的。
随机数
rand
包实现了伪随机数的生成。
1 | package main |
函数 rand.Intn
返回介于 [0, n) 之间的伪随机数。
类型别名
在 type TZ int
中,TZ 就是 int 类型的新名称(用于表示程序中的时区),然后就可以使用 TZ 来操作 int 类型的数据。
新类型不会拥有原类型所附带的方法。
字符类型
byte
类型是 uint8
的别名。
Go 同样支持 Unicode(UTF-8),因此字符同样称为 Unicode 代码点或者 runes,并在内存中使用 int 来表示。
rune
也是 Go 当中的一个类型,并且是 int32
的别名。
1 | var ch byte = 65 或 var ch byte = '\x41' |
var ch byte = 'A'
;字符使用单引号括起来。
Unicode 至少占用 2 个字节,所以我们使用 int16
或者 int
类型来表示。如果需要使用到 4 字节,则会加上 \U
前缀;前缀 \u
则总是紧跟着长度为 4 的 16 进制数,前缀 \U
紧跟着长度为 8 的 16 进制数。
1 | var ch int = '\u0041' |
- 判断是否为字母:
unicode.IsLetter(ch)
- 判断是否为数字:
unicode.IsDigit(ch)
- 判断是否为空白符号:
unicode.IsSpace(ch)
包 utf8
拥有更多与 rune 类型相关的函数。
字符串
字符串是一种值类型,且值不可变,字符串是字节的定长数组。
Go 中的字符串是根据长度限定,而非特殊字符\0
。
函数 len()
来获取字符串所占的字节长度。
在循环中使用加号 +
拼接字符串并不是最高效的做法,更好的办法是使用函数 strings.Join()。
使用字节缓冲(bytes.Buffer
)拼接更加给力。
strings和strconv包
Go 中使用 strings
包来完成对字符串的主要操作。
1 | strings.HasPrefix(s, prefix string) bool |
与字符串相关的类型转换都是通过 strconv
包实现的。
1 | strconv.Itoa(i int) string |