运算符 -- 就要学习 Go 语言

2,311 阅读6分钟

今天,我们来讲下Go语言的算术运算符、比较运算符和逻辑运算符。

算术运算符

+    sum                    integers, floats, complex values (复数), strings
-    difference             integers, floats, complex values
*    product                integers, floats, complex values
/    quotient               integers, floats, complex values
%    remainder              integers

位运算符:
&    bitwise AND (按位与)                integers
|    bitwise OR (按位或)                 integers
^    bitwise XOR (按位异或)              integers
&^   bit clear (AND NOT 按位置零)        integers

移位运算符:
<<   left shift             integer << unsigned integer
>>   right shift            integer >> unsigned integer

算术运算符+-*/适用于整数、浮点数和复数,+也适用于字符串,用于字符串连接;取模运算%仅适用整数间的运算,Go语言中,%取模运算符的结果的符号和被取模数的符号总是一致的,因此-5%3-5%-3结果都是-2。除法运算符/的结果依赖于操作数是否为全为整数,比如5.0/4.0的结果是1.25,但是5/4的结果是1,因为整数除法会向着0方向截断余数;位运算和移位运算只适用整型。 位操作运算符^,作为一元运算符,表示按位取反,就是说,它返回一个每个bit位都取反的数:作用类似在C、C#、Java语言中中符号~,对于有符号的整数来说,是按照补码进行取反操作的(快速计算方法:对数a取反,结果为-(a+1) );对于无符号整数来说就是按位取反。

var a int8 = 3
var b uint8 = 3
var c int8 = -3

fmt.Printf("^%b=%b %d\n", a, ^a, ^a) // ^11=-100 -4
fmt.Printf("^%b=%b %d\n", b, ^b, ^b) // ^11=11111100 252
fmt.Printf("^%b=%b %d\n", c, ^c, ^c) // ^-11=10 2

输出:

^11=-100 -4
^11=11111100 252
^-11=10 2

作为二元运算符时是按位异或:对应位,相同为0,相异为1。

var a int8 = 3
var c int8 = 5

fmt.Printf("a: %08b\n",a)
fmt.Printf("c: %08b\n",c)
fmt.Printf("a^c: %08b\n",a ^ c)

输出:

a: 00000011
c: 00000101
a^c: 00000110

加法和减法运算符:+-也可以作为一元操作符: 对于整数,+x0+x的简写,-x则是0-x的简写;对于浮点数和复数,+x就是x-x则是x的负数。 需要给大家提一下的是这个操作符:按位置零&^,表达式z = x &^ y,如果 y 中的bit位为1,则 z 对应bit位为0,否则 z 对应bit位等于 x 中相应的bit位的值。不知道大家发现没有,我们还可以这样理解或操作符|,表达式z = x | y,如果 y 中的bit位为1,则 z 对应bit位为1,否则 z 对应bit位等于 x 中相应的bit位的值,与&^完全相反。

var x uint8 = 214
var y uint8 = 92
fmt.Printf("x: %08b\n",x)
fmt.Printf("y: %08b\n",y)
fmt.Printf("x|y: %08b\n",x | y)
fmt.Printf("x&^y: %08b\n",x &^ y)

输出:

x: 11010110
y: 01011100
x|y: 11011110
x&^y: 10000010

移位运算符x<<nx>>n,如果左边的操作数是有符号整型,则是算术移位;如果左边的操作数是无符号整型,则是逻辑移位。逻辑移位不用考虑符号位,而算术移位需要考虑符号位,这样能保证移位操作乘除的操作一致。对于x<<1,相当于x*2x>>1,相当于x/2;左移算术移位结果会向下取整:

var a int8 = -51
fmt.Println("a:")
fmt.Printf("%08b\n",a)
fmt.Printf("%d: %08b\n", a>>1, a>>1)

var b int8 = 51
fmt.Println("b:")
fmt.Printf("%08b\n",b)
fmt.Printf("%d: %08b\n", b>>1, b>>1)

var i uint8 = 1
fmt.Println("i:")
fmt.Printf("%d: %08b\n", i<<1, i<<1) //2: 00000010
fmt.Printf("%d: %08b\n", i<<7, i<<7) //128: 10000000
fmt.Printf("%d: %b\n", i<<8, i<<8) //0: 0
var i2 int8 = 1
fmt.Println("i2:")
fmt.Printf("%d: %08b\n", i2<<1, i2<<1) //2: 00000010
fmt.Printf("%d: %08b\n", i2<<7, i2<<7) //-128: -10000000
fmt.Printf("%d: %b\n", i2<<8, i2<<8) //0: 0
var i3 int8 = -1
fmt.Println("i3:")
fmt.Printf("%d: %08b\n", -i3<<1, -i3<<1) //2: 00000010
fmt.Printf("%d: %08b\n", -i3<<7, -i3<<7) //-128: -10000000
fmt.Printf("%d: %b\n", -i3<<8, -i3<<8) //0: 0
var i4 int8 = -128
fmt.Println("i4:")
fmt.Printf("%d: %08b\n", -i4>>0, -i4>>0) //-128: -10000000
fmt.Printf("%d: %08b\n", -i4>>1, -i4>>1) //-64: -1000000
fmt.Printf("%d: %b\n", -i4>>2, -i4>>2) //-32: -100000

输出:

a:
-0110011
-26: -0011010
b:
00110011
25: 00011001
i:
2: 00000010
128: 10000000
0: 0
i2:
2: 00000010
-128: -10000000
0: 0
i3:
2: 00000010
-128: -10000000
0: 0
i4:
-128: -10000000
-64: -1000000
-32: -100000

字符串连接可以使用++=运算符:

c := " Seekload"
s := "Hi" + string(c)
s += ", good bye"

整型溢出: 有符号整数的+-*<<的操作的结果的溢出不会导致异常,但结果可能不是你想要的,比如x < x+1并不总是成立,比如:

var x int8 = 127;
fmt.Printf("%d\n",x+2)   //输出 -127

无符号整数的+、-、*、<<的操作的结果会取模2^n, 也就是溢出的位会被丢掉, 比如:

var x uint8 = 255;
fmt.Printf("%d\n",x+2)    // 输出:1

比较运算符

两个相同的整数类型可以使用下面的二元比较运算符进行比较,比较表达式的结果是布尔类型。

布尔型、数字类型和字符串等基本类型都是可比较的,一些基本的比较操作我就不在这列举了,大家可以实操下,等大家学到后面,我会开一个篇文章详解比较运算符。

逻辑运算符

符号  说明
&&   逻辑与  (p && q)  p、q全为true,(p && q)才为true
||   逻辑或  (p || q)  p、q至少一个为true,(p || q)就为true
!   逻辑非   !p  若p为true,则!p为false;若p为false,则!p为true;

运算符优先级

一元运算符有最高的优先级。操作符++--只能构成语句,而不是表达式,因为它们不属于运算符序列。 下面是关于算术运算、逻辑运算和比较运算的二元运算符,按照优先级递减的顺序排列:

优先级   操作符
  5     *  /  %  <<  >>  &  &^
  4     +  -  |  ^
  3     ==  !=  <  <=  >  >=    
  2     &&
  1     ||

从上面可以看出,二元运算符有五种优先级。在同一个优先级,使用左优先结合规则,但是使用括号可以明确优先顺序,使用括号也可以用于提升优先级,例如:mask & (1 << 28)


(全文完)

原创文章,若需转载请注明出处!
欢迎扫码关注公众号「Golang来啦」或者移步 seekload.net ,查看更多精彩文章。

公众号「Golang来啦」给你准备了一份神秘学习大礼包,后台回复【电子书】领取!

公众号二维码