Golang 中的数字包括整型(整数)、实型(浮点数)、复数、布尔型和常量,下面就分别来解释它们

整型

众所周知 C/C++ 中对于一般整型使用的关键字是 shortintlonglong long 之类的,而 Go 中直接根据占用的 bit 大小命名为 int8int16int32int64

而对于一票带 unsigned 关键字的无符号整型,就直接命名为 uint8uint16uint32uint64

那么在 Go 中有没有 int 呢?答案是有的

Go 中还有 intuint,它们的大小根据实际软硬件平台不同而不同,一般是 32 bit,日常来说完全够用,但是要记住 intint32 必须显式地转换,即使它们的大小一般是相同的

还有有两种衍生类型需要了解:

  • rune :与 int32 等价,用于表示一个 Unicode 码点
  • byte :与 uint8 等价,一般用于强调数值是一个原始的数据而不是一个小的整数

还有一种特殊的类型 uintptr ,它没有指定的大小,用来保存指针,只在底层编程时用到,一般见不到

实型

Go 中的浮点数只有 float32float64 两种,一般情况下建议直接使用 float64,它们都向下兼容 C/C++ 中的用法

不过 Go 中的数学运算与 C 中的有一些不同:

  • 算术和逻辑运算的二元操作中必须是相同的类型,也就是说不会像 C 一样隐式转换(浮点数等同理)

  • Go 在 math 包中添加了 IEEE754 浮点数标准中定义的特殊值:正无穷大和负无穷大(+Inf-Inf ,用于表示太大溢出的数字和除零的结果),非数(NaN,含义是 Not a number,用于表示无效的除法操作结果 0/0Sqrt(-1)

    1
    2
    var z float64
    fmt.Println(z, -z, 1/z, -1/z, z/z) // "0 -0 +Inf -Inf NaN"

    函数 math.IsNaN 用于测试一个数是否是非数 NaNmath.NaN 则返回非数对应的值。虽然可以用 math.NaN 来表示一个非法的结果,但是测试一个结果是否是非数 NaN 则是充满风险的,因为 NaN 和任何数都是不相等的

    1
    2
    nan := math.NaN()
    fmt.Println(nan == nan, nan < nan, nan > nan) // "false false false"
  • 添加了一个位运算操作 &^ (位清空)

复数

Go 语言提供了两种精度的复数类型:complex64complex128,分别对应 float32 float64 两种浮点数精度

使用内置的 complex() 函数可以构建复数,real()imag() 可以返回复数的实部和虚部

1
2
3
4
5
var x complex128 = complex(1, 2) // 1+2i
var y complex128 = complex(3, 4) // 3+4i
fmt.Println(x*y) // "(-5+10i)"
fmt.Println(real(x*y)) // "-5"
fmt.Println(imag(x*y)) // "10"

当然,你也可以使用自然书写方式构建复数

1
2
x := 1 + 2i
y := 3 + 4i

布尔型

Go 中的布尔型(truefalse)与 C++ 中的一致

常量

Go 中的常量与 C/C++ 中的变化不大

1
const pi float64 = 3.14159 

当然,Go 也允许你忽略类型,自动判断

1
const pi = 3.14159 

多常量一起声明也是允许的

1
2
3
4
const (
e = 2.71828182845904523536028747135266249775724709369995957496696763
pi = 3.14159265358979323846264338327950288419716939937510582097494459
)

批量声明相同数值的常量可以像这样省略

1
2
3
4
5
6
7
8
const (
a = 1
b
c = 2
d
)

fmt.Println(a, b, c, d) // "1 1 2 2"

iota 常量生成器

我感觉这属于一种比较鸡肋的东西,但是还是有一些作用的

它可以生成一组以相似规则初始化的常量,不用每行都写一遍初始化表达式

举个例子最清楚

1
2
3
4
5
6
7
8
9
10
11
type Weekday int

const (
Sunday Weekday = iota
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
)

周日将对应0,周一为1,如此等等

你可以用它玩出一些新花样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const (
Zero = iota // 0
First // 1
Second // 2
Hi = 0 // 0, 被打断后,后续值不变,直到用iota显示恢复
Four // 0
Five // 0
Six = iota // 6,显示恢复,iota接着累加,中间打断不中断累加
Seven // 7
Eight = iota * 10 // 80,iota不变,变更常量表达式,后续保持表达式
Nine // 90
)

const (
TenZero = iota * 10 // 0,表达式可以为各种go支持的计算表达式
TenFirst // 10
TenSecond // 20
)