Press "Enter" to skip to content

Go 数据类型篇(三):整型及运算符

整型

整型是所有编程语言里最基础的数据类型,Go 语言默认支持如下这些整型类型:

类型长度(单位:字节)说明值范围默认值
int81带符号8位整型-128~1270
uint81无符号8位整型,与 byte 类型等价0~2550
int162带符号16位整型-32768~327670
uint162无符号16位整型0~655350
int324带符号32位整型,与 rune 类型等价-2147483648~21474836470
uint324无符号32位整型0~42949672950
int648带符号64位整型-9223372036854775808~92233720368547758070
uint648无符号64位整型0~184467440737095516150
int32位或64位与具体平台相关与具体平台相关0
uint32位或64位与具体平台相关与具体平台相关0
uintptr与对应指针相同无符号整型,足以存储指针值的未解释位32位平台下为4字节,64位平台下为8字节0

Go 支持的整型类型非常丰富,你可以根据需要设置合适的整型类型,以节省内存空间,此外 intint32 在 Go 语言里被认为是两种不同的类型(同理,intint64 也是不同的类型),编译器也不会帮你自动做类型转换,比如以下的例子会有编译错误:

var intValue1 int8
intValue2 := 8   // intValue2 将会被自动推导为 int 类型 
intValue1 = intValue2  // 编译错误

编译错误类似于:

 cannot use intValue2 (type int) as type int8 in assignment

使用强制类型转换可以解决这个编译错误:

intValue1 = int8(intValue2)) // 编译通过

注:关于类型转换我们在后面介绍完所有数据类型后会单独介绍。

我们还可以通过 intValue := uint8(intValue2) 这种方式同时完成类型转化和赋值操作。

此外,和其他编程语言一样,可以通过增加前缀 0 来表示八进制数(如:077),增加前缀 0x 来表示十六进制数(如:0xFF),以及使用 E 来表示 10 的连乘(如:1E3 = 1000)。

运算符

算术运算符

Go 语言支持所有常规的整数四则运算:+-*/%(取余运算只能用于整数),不过由于强类型的关系,在 Go 语言中,不同类型的整型值不能直接进行算术运算,比如下面这样计算就会报编译错误:

intValue3 := intValue1 + intValue2

编译错误信息如下:

invalid operation: intValue1 + intValue2 (mismatched types int8 and int)

类型转化之后就好了:

intValue3 := intValue1 + int8(intValue2)

如果你是从动态语言转过来学习 Go,在刚开始写代码时尤其要注意这些因为类型问题产生的 bug。

在 Go 语言中,也支持自增/自减运算符,即 ++/--,但是只能作为语句,不能作为表达式,且只能用作后缀,不能放到变量前面:

intValue1++  // 有效,intValue1 的值变成 9
intValue1 = intValue1++ // 无效,编译报错
--intValue1  // 无效,编译报错

还支持 +=-=*=/=%= 这种快捷写法:

intValue1 += intValue1 // 18
intValue1 -= intValue1 // 0
intValue1 *= intValue1 // 81
intValue1 /= intValue1 // 1
intValue1 %= intValue1 // 0

比较运算符

Go 语言支持以下几种常见的比较运算符: ><==>=<=!=,比较运算符运行的结果是布尔值。

上篇教程所说,Go 是强类型语言,不同类型的值不能放在一起比较,否则会报编译错处:

if intValue1 == intValue2 {
    fmt.Println("intValue1 和 intValue2 相等")
}

相同类型的值才可以:

if intValue1 < intValue3 {
    fmt.Println("intValue1 比 intValue3 小")
}

由此可见,所有比较运算符在比较的时候都会考虑进数据类型的因素,所以不需要额外引入类似 PHP 等动态语言中的 ===!== 这种严格比较运算符。

不过,各种类型的整型变量都可以直接与字面常量进行比较,比如:

if intValue1 == 8 {
    fmt.Println("intValue1 = 8")
}

位运算符

位运算符以二进制的方式对数值进行运算,效率更高,性能更好,Go 语言支持以下这几种位运算符:

运算符含义结果
x & y按位与把 x 和 y 都为 1 的位设为 1
x | y按位或把 x 或 y 为 1 的位设为 1
x ^ y按位异或把 x 和 y 一个为 1 一个为 0 的位设为 1
^x按位取反把 x 中为 0 的位设为 1,为 1 的位设为 0
x << y左移把 x 中的位向左移动 y 次,每次移动相当于乘以 2
x >> y右移把 x 中的位向右移动 y 次,每次移动相当于除以 2

我们可以做一些简单的测试:

var intValueBit uint8
intValueBit = 255
intValueBit = ^intValueBit // 按位取反
fmt.Println(intValueBit)   // 0
intValueBit = 1
intValueBit = intValueBit << 3 // 左移 3 位,相当于乘以 2^3 = 8
fmt.Println(intValueBit)       // 8

逻辑运算符

Go 语言支持以下逻辑运算符:

运算符含义结果
x && y逻辑与运算符(AND)如果 x 和 y 都是 true,则结果为 true,否则结果为 false
x || y逻辑或运算符(OR)如果 x 或 y 是 true,则结果为 true,否则结果为 false
!x逻辑非运算符(NOT)如果 x 为 true,则结果为 false,否则结果为 true

逻辑运算符计算的结果也是布尔值,通常我们可以组合使用逻辑运算符和比较运算符:

if intValue1 < intValue3 && intValue1 == 8 {
    fmt.Println("条件为真")
}

运算符优先级

上面介绍的 Go 语言运算符优先级如下所示(由上到下表示优先级从高到低,或者数字越大,优先级越高):

6      ^(按位取反) !
5      *  /  %  <<  >>  &  &^
4      +  -  |  ^(按位异或)
3      ==  !=  <  <=  >  >=
2      &&
1      ||

++-- 只能出现在语句中,不能用于表达式,故不参与优先级判断。

2 Comments

发表回复