首页 > 编程笔记

Go语言运算符详解

编程的运算符好比数学的加减乘除等运算法则,每一种编程语言的运算符都是大同小异的。

Go语言支持以下类型的运算符:

算术运算符

算术运算符就是我们常说的加减乘除法则,主要在程序里实现简单的数学计算。

Go 语言的算术运算符如下表所示:
运算符 描 述 实  例
+ 加法,两个变量相加 x = 2+3,x 的值为 5
- 减法,两个变量相减或者用于负数的表示 x = 2-3, x 的值为 -1
* 乘法,两个变量的数值相乘 x = 2*3, x 的值为 6
/ 除法,两个变量的数值相除 x = 9/2,x 的值为 4.5
% 求余,获取除法中的余数 x = 9%2,x 的值为 1
++ 自增加 1 x++,x 的值为 8,自增后为 9
-- 自减去 1 x-- ,x 的值为 8,自减后为 7

下面通过实例演示 Go 语言算术运算符的用法,代码如下:
package main

import "fmt"

func main(){
    var x, y = 8, 5
    fmt.Printf("加法运算符:%d\n", x+y)
    fmt.Printf("减法运算符:%d\n", x-y)
    fmt.Printf("乘法运算符:%d\n", x*y)
    fmt.Printf("除法运算符:%d\n", x/y)
    fmt.Printf("求余运算符:%d\n", x%y)
    x++
    fmt.Printf("幂运算符:%d\n", x)
    y--
    fmt.Printf("取整运算符:%d\n", y)
}
在 GoLand 中运行上述代码,结果为:

加法运算符:13
减法运算符:3
乘法运算符:40
除法运算符:1
求余运算符:3
幂运算符:9
取整运算符:4

关系运算符

关系(比较)运算符是比较两个变量之间的大小关系,而且两个变量的数据类型必须相同,比较结果以 true 或者 false 返回。

关系运算符如下表所示:

运算符 描  述 实  例
== 等于,判断比较运算符前面的变量是否等于后面的变量 2==3,比较结果为 false
!= 不等于,判断比较运算符前面的变量是否不等于后面的变量 2!=3,比较结果为 true
> 大于,判断比较运算符前面的变量是否大于后面的变量 2>3,比较结果为 false
< 小于,判断比较运算符前面的变量是否小于后面的变量 2<3,比较结果为 true
>= 大于等于,判断比较运算符前面的变量是否大于或等于后面的变量 2>=3,比较结果为 false
<= 小于等于,判断比较运算符前面的变量是否小于或等于后面的变量 2<=3,比较结果为 true

下面通过实例演示关系运算符的用法,代码如下:
package main

import "fmt"

func main(){
    var x, y = 8, 5
    fmt.Printf("x大于y:%v\n", x > y)
    fmt.Printf("x大于或等于y:%v\n", x >= y)
    fmt.Printf("x小于y:%v\n", x < y)
    fmt.Printf("x小于或等于y:%v\n", x <= y)
    fmt.Printf("x等于y:%v\n", x == y)
    fmt.Printf("x不等于y:%v\n", x != y)
}
在GoLand中运行代码,运行结果为:

x大于y:true
x大于或等于y:true
x小于y:false
x小于或等于y:false
x等于y:false
x不等于y:true

赋值运算符

赋值运算符是算术运算符的一个特殊使用,其实质是两个变量进行算术运算并将运算结果重新赋值给其中一个变量。

赋值运算符如下表所示:

运算符 描  述 实  例
= 简单的赋值运算符 c=a+b,将 a+b 的运算结果赋值给 c
+= 加法赋值运算符 c+=a,等效于 c=c+a
-= 减法赋值运算符 c-=a,等效于 c=c-a
*= 乘法赋值运算符 c*=a,等效于 c=c*a
/= 除法赋值运算符 c/=a,等效于 c=c/a
%= 求余赋值运算符 c%=a,等效于 c=c%a
<<= 按位左移赋值运算符 c<<=2,等效于 c=c<<2
>>= 按位右移赋值运算符 c>>=2,等效于 c=c>>2
&= 按位与赋值运算符 c&=2,等效于 c=c&2
^= 按位异或赋值运算符 c^=2,等效于 c=c^2
|= 按位或赋值运算符 c|=2,等效于 c=c|2

下面通过实例演示赋值运算符的用法,具体代码如下:
package main

import "fmt"

func main() {
    var a, c int = 21, 0
    c = a
    fmt.Printf("=运算符实例,c值为 = %d\n", c)
    c, a = 1, 20
    c +=  a
    fmt.Printf("+=运算符实例,c值为 = %d\n", c)
    c, a = 1, 20
    c -=  a
    fmt.Printf("-=运算符实例,c值为 = %d\n", c)
    c, a = 1, 20
    c *=  a
    fmt.Printf("*=运算符实例,c值为 = %d\n", c)
    c, a = 1, 20
    c /=  a
    fmt.Printf("/=运算符实例,c值为 = %d\n", c)
    c, a = 1, 20
    c %=  a
    fmt.Printf("求余运算符实例,c值为 = %d\n", c)
    c = 200
    c <<=  2
    fmt.Printf("<<=运算符实例,c值为 = %d\n", c)
    c = 200
    c >>=  2
    fmt.Printf(">>=运算符实例,c值为 = %d\n", c)
    c = 200
    c &=  2
    fmt.Printf("&=运算符实例,c值为 = %d\n", c)
    c = 200
    c ^=  2
    fmt.Printf("^=运算符实例,c值为 = %d\n", c)
    c = 200
    c |=  2
    fmt.Printf("|=运算符实例,c值为 = %d\n", c)
}
由于每次进行赋值运算后,变量 x 的数值都会发生变化,因此执行下次赋值运算时必须重设变量 x 的数值。

运行上述代码,运行结果为:

=运算符实例,c值为 = 21
+=运算符实例,c值为 = 21
-=运算符实例,c值为 = -19
*=运算符实例,c值为 = 20
/=运算符实例,c值为 = 0
求余运算符实例,c值为 = 1
<<=运算符实例,c值为 = 800
>>=运算符实例,c值为 = 50
&=运算符实例,c值为 = 0
^=运算符实例,c值为 = 202
|=运算符实例,c值为 = 202

在所有赋值运算符中,难以理解的运算符有:按位左移赋值运算符、按位右移赋值运算符、按位与赋值运算符、按位异或赋值运算符、按位或赋值运算符。这些运算符皆与位运算相关,用于对二进制数值进行计算处理。

逻辑运算符

逻辑运算符是将多个条件进行与、或、非的逻辑判断,这种运算符常用于条件判断。

逻辑运算符如下表所示:

运算符 描  述 实  例
&& (与) x&&y: x和y的值只能为布尔型
若 x 或 y 为 false,则返回 false
若 x 和 y 皆为 true,则返回 true
false && true,返回 false
false && false,返回 false
true && true,返回 true
II (或) x||y:x 和 y 的值只能为布尔型
若 x 或 y 为 true,则返回 true
若 x 和 y 皆为 false,则返回 false
false || true,返回 true
true || true,返回 true 
false || false,返回 false
!(非) !x:x 的值只能为布尔型
若 x 为 true,则返回 false
若 x 为 false,则返回 true
!false,返回 true
!true,返回 false

逻辑运算符的与、或、非只能对两个布尔类型的变量进行判定,下面通过实例简单演示逻辑运算符的用法,代码如下:
package main

import "fmt"

func main() {
    var a, b, c, d = true, true, false, false
    fmt.Printf("a&&b的值为:%v\n", a && b)
    fmt.Printf("a&&c的值为:%v\n", a && c)
    fmt.Printf("c&&d的值为:%v\n", c && d)
    fmt.Printf("a||b的值为:%v\n", a || b)
    fmt.Printf("a||c的值为:%v\n", a || c)
    fmt.Printf("c||d的值为:%v\n", c || d)
    fmt.Printf("!a的值为:%v\n", !a)
    fmt.Printf("!c的值为:%v\n", !c)
}
在GoLand中运行上述代码,运行结果为:

a&&b的值为:true
a&&c的值为:false
c&&d的值为:false
a||b的值为:true
a||c的值为:true
c||d的值为:false
!a的值为:false
!c的值为:true

位运算符

位运算符是将数值转换为二进制进行计算。我们无须手动将数值转换为二进制,只需对数值使用位运算符即可。

位运算符如下表所示:

运算符 描  述 实  例
& 按位与运算符,参与运算的两个值,如果两个相应位都为 1,那么该位的结果为 1,否则为 0 60 & 13 输出结果为 12,二进制为
0000 1100
| 按位或运算符,只要对应的两个二进制位有一个为 1,结果就为 1 60 | 13 输出结果为 61,二进制为
0011 1101
^ 按位异或运算符,当两个对应的二进制位相异时,结果为 1 60^13 输出结果为 49,二进制为
0011 0001
<< 左移运算符,将二进制位全部左移若干位,由“<<” 右边的数指定移动的位数,高位丢弃,低位补 0 60<<2 输出结果为 240,二进制为
1111 0000
>> 右移运算符,将二进制位全部右移若干位,由“>>”右边的数指定移动的位数,移动过程中,正数最高位补 0,负数最高位补 1,无符号数最高位补 0 60>>2 输出结果为 15,二进制为
0000 1111

下面通过实例演示位运算符的具体使用方式,代码如下:
package main

import "fmt"

func main() {

    var a = 60      // 60 = 0011 1100
    var b = 13      // 13 = 0000 1101
    var c = 0

    c = a & b       // 12 = 0000 1100
    fmt.Printf("c的十进制值为 %d\n", c )
    fmt.Printf("c的二进制值为 %b\n", c )

    c = a | b       // 61 = 0011 1101
    fmt.Printf("c的十进制值为 %d\n", c )
    fmt.Printf("c的二进制值为 %b\n", c )

    c = a ^ b       // 49 = 0011 0001
    fmt.Printf("c的十进制值为 %d\n", c )
    fmt.Printf("c的二进制值为 %b\n", c )

    c = a << 2     // 240 = 1111 0000
    fmt.Printf("c的十进制值为 %d\n", c )
    fmt.Printf("c的二进制值为 %b\n", c )

    c = a >> 2     // 15 = 0000 1111
    fmt.Printf("c的十进制值为 %d\n", c )
    fmt.Printf("c的二进制值为 %b\n", c )
}
在GoLand中运行上述代码,运行结果为:

c的十进制值为 12
c的二进制值为 1100
c的十进制值为 61
c的二进制值为 111101
c的十进制值为 49
c的二进制值为 110001
c的十进制值为 240
c的二进制值为 11110000
c的十进制值为 15
c的二进制值为 1111

其他运算符

Go 语言还设有其他运算符,分别是“&”和“*”,说明如下表所示:

运算符 描  述 实  例
& 获取变量的内存地址 &a
* 指针变量 *a 设置为指针变量
下面通过实例演示其他运算符的使用方法:
package main

import "fmt"

func main() {
    var a = 4
    var ptr *int
    fmt.Printf("a变量的内存地址:%v\n", &a)
    // 将变量a的内存地址赋给指针ptr
    ptr = &a
    fmt.Printf("指针ptr的内存地址为:%v\n", ptr)
    fmt.Printf("指针ptr的值为:%v\n", *ptr)
}
在GoLand中运行上述代码,运行结果为:

a变量的内存地址:0xc0000180a8
指针ptr的内存地址为:0xc0000180a8
指针ptr的值为:4

运算符优先级

不同的运算符有不同的优先级,在一行语句中使用了多种不同类型的运算符,程序根据运算符优先级决定运算符的执行顺序。

所有运算符的优先级如下表所示:

优先级 运算符 同一运算符的优先级
1 ,(逗号) 从左到右
2 =、+=、-=、*=、/=、%=、>>=、<<=、&=、^=、|= 从右到左
3 || 从左到右
4 && 从左到右
5 | 从左到右
6 ^ 从左到右
7 & 从左到右
8 ==、!= 从左到右
9 <、<=、>、>= 从左到右
10 <<、>> 从左到右
11 +、- 从左到右
12 * (乘号)、/、% 从左到右
13 !、*(指针)、&、++、-、+(正号)、-(负号) 从右到左
14 ()、[]、-> 从左到右

优先级越高的运算符执行顺序越高,优先级越低的运算符执行顺序越低。大部分同一优先级的运算符按照从左到右的顺序执行,只有个别运算符按照从右到左的顺序执行。

推荐阅读