2.6 运算符
运算符用于在程序运行时执行数学或逻辑运算。Go语言内置的运算符有算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符和特殊运算符(&是取地址运算符,*是取地址所对应的值的运算符,这与C语言很类似)。在日常的编程中,比较常用的是算术运算符、关系运算符、逻辑运算符和赋值运算符,而位运算符一般用得较少。
运算符和变量或常量等按照一定的次序连接起来构成表达式(Expression),例如算术表达式、逻辑表达式等。下面分别对Go语言内置的运算符进行详细说明。
2.6.1 算术运算符
算术运算符可以在数值间进行四则运算,也就是加减乘除等操作。下面是算术运算符基本用法的示例程序2-15。
示例程序2-15 算术运算符基本用法:chapter02\code07\opt_num.go
在示例程序2-15中,需要注意的是:Go语言的自增运算符++和自减运算符--,它们不能出现在表达式的末尾,也就是说,数值的自增和自减操作不能赋值给其他变量。Go语言中没有内置的求幂(Power)函数,需要开发者自行实现。
注意
在Go语言中,整数类型和浮点类型的变量不能直接进行四则运算,否则会报类型不匹配的错误。
2.6.2 关系运算符
关系运算符用来比较两个值的大小关系,例如大于、小于、大于等于,等等。关系运算符的结果总是布尔值,即要么是true,要么是false。下面是关系运算符基本用法的示例程序2-16。
示例程序2-16 关系运算符基本用法:chapter02\code07\opt_relation.go
在示例程序2-16中,第05行声明了两个整数类型的变量a和b,并把11和2分别赋值给它们。07行用关系运算符==来比较变量a和b的值是否相等,同时将判断结果赋值给新声明的变量c。从程序中可以看出关系运算符“==”的优先级高于变量赋值运算符“:=”。
注意
在Go语言中,整数类型和浮点类型的变量不能直接进行大小比较,否则会报类型不匹配的错误。
2.6.3 逻辑运算符
逻辑运算符有非(!)、与(&&)和或(||)3种。逻辑运算符&&和||是双目运算符,两边表达式的结果值必须是true或者false。逻辑非总是取后缀值的相反值;逻辑与运算符两边表达式的结果都是true,逻辑运算的结果值才为true,只要有一个为false则逻辑运算的结果值为false;逻辑或运算符两边表达式的结果都是false,逻辑运算的结果值才为false,只要有一个为true则逻辑运算的结果值为true。下面是逻辑运算符基本用法的示例程序2-17。
示例程序2-17 逻辑运算符基本用法:chapter02\code07\opt_logic.go
在示例程序2-17中,第05行先声明了两个整数类型的变量a和b,并把11和2分别赋值给它们。第06行声明了一个布尔类型的变量isOk,并将它赋值为false。第09行输出表达式a > b &&isOk的逻辑值,由于&&是逻辑与运算符,操作数全为true时这个逻辑表达式的结果才能为true,因为其中的isOk为false,所以表达式的结果为false。另外,从这个表达式也能推断出关系运算符的优先级比逻辑运算符的优先级高。
注意
在Go语言中,逻辑运算符只能作用于布尔类型的值,不能对整数类型等数据进行操作,比如!0。
2.6.4 位运算符
位运算符是对整数在内存中的二进制位进行操作,一般情况下,位运算符使用的比较少。位运算符有按位与(&)、按位或(|)、按位异或(^)、左移(<<)和右移(>>)。下面是位运算符基本用法的示例程序2-18。
示例程序2-18 位运算符基本用法:chapter02\code07\opt_bit.go
在示例程序2-18中,为了清晰地说明位运算符,第06行声明了两个二进制格式的变量a和b,其值分别为0b00111100、0b10001101。其中,0b打头表示该数值是二进制表示法。第08行输出a&b的值。按位与运算符只有对应二进制位的数都为1,运算结果才为1,否则为0,因此,a&b运算结果值的二进制表示为00001100,即1100,如图2.11所示。
图2.11 a和b位运算示意图
2.6.5 赋值运算符
在对变量进行赋值时,就要用到赋值运算符,它的种类也比较多,上面讲的算术运算符、逻辑运算符、关系运算符和位运算符几乎(不是全部,除了!单目运算符)都可以与基本的赋值运算符(=)进行组合,生成新的复合赋值运算符。下面是赋值运算符基本用法的示例程序2-19。
示例程序2-19 赋值运算符基本用法:chapter02\code07\opt_assign.go
2.6.6 特殊运算符
在Go语言中,存在两个特殊的运算符,即&和*:&是取地址运算符;*是取地址所对应的值的运算符。这里需要注意与位运算符&和算术运算符*的区别。如果学过C语言,那么对这个特殊运算符会更好理解一点。下面是特殊运算符基本用法的示例程序2-20。
示例程序2-20 特殊运算符基本用法:chapter02\code07\opt_other.go
在示例程序2-20中,第05行声明了两个变量a和b,其中a是整数类型、b是字符串类型。第07行和第08行分别用&a和&b获取变量a和b的内存地址。第09行和第10行分别打印输出这两个内存地址,这里需要注意的是打印的内存地址会根据编译的计算机不同而有所差异。第12行和第13行用*p和*p1来间接引用目标对象a和b。因此,第14行输出了变量a的值2,而第15行输出了变量b的值Hello。
2.6.7 运算符的优先级
在四则运算中,先计算乘除后计算加减,说明乘除运算符的优先级比加减运算符的优先级高。所谓优先级,就是当多个运算符出现在同一个表达式中时运算符执行次序的高低。
Go语言有几十种运算符,被分成十几个优先级,有的运算符优先级不同,有的运算符优先级相同,如表2.1所示。
表2.1 Go运算符优先级
优先级值越大,表示优先级越高,比如优先级12的乘除比优先级11的加减优先级高。对于复杂的表达式,记住表2.1中所有的优先级是很难的,而且代码可读性很差。我们可以通过使用括号来改变某个表达式的整体运算优先级,并使得表达式的可读性更好。