运算符 | 优先级 |
---|---|
^ ! | 7 |
* / % << >> & &^ | 6 |
+ - | ^ | 5 |
== != < <= >= > | 4 |
<- | 3 |
&& | 2 |
|| | 1 |
上表列出了所有运算符以及它们的优先级,由上至下代表优先级由高到低
但可以通过使用括号来临时提升某个表达式的整体运算优先级
一元运算符:可以用于一个值的操作(作为后缀)
二元运算符:可以和两个值或者操作数结合(作为中缀)
有些运算符拥有较高的优先级,二元运算符的运算方向均是从左至右
一、关系运算符
Go 中拥有以下逻辑运算符:== !=
<
<= > >=
它们之所以被称为逻辑运算符是因为它们的运算结果总是为布尔值 bool
。例如:
val:= 2 > 1 // val is true
Go 对于值之间的比较有非常严格的限制,只有两个类型相同的值才可以进行比较,如果值的类型是接口interface,它们也必须都实现了相同的接口。如果其中一个值是常量,那么另外一个值的类型必须和该常量类型相兼容的。如果以上条件都不满足,则其中一个值的类型必须在被转换为和另外一个值的类型相同之后才可以进行比较
两个类型相同的值可以使用相等 == 或者不等 != 运算符来进行比较并获得一个布尔型的值。当相等运算符两边的值是完全相同的值的时候会返回 true,否则返回 false
二、逻辑运算符
布尔型的常量和变量可以通过和逻辑运算符(非 !
、和 &&
、或 ||
)结合来产生另外一个布尔值
非运算符 ! 用于取得和布尔值相反的结果
!true -> false
!false -> true
两个变量参与 && 运算时,只有当两个变量均为true时,运算结果才为true,否则结果为false
true && true -> true
true && false -> false
false && true -> false
false && false -> false
两个变量参与 || 运算时,当两个变量有一个为true时,结果即为true,只有当两个变量均为false时结果为false
true || true -> true
true || false -> true
false || true -> true
false || false -> false
在 Go 语言中,&& 和 || 是具有快捷性质的运算符,当运算符左边表达式的值已经能够决定整个表达式的值的时候(&& 左边的值为 false,|| 左边的值为 true),运算符右边的表达式将不会被执行。利用这个性质,如果你多个条件判断,应当将计算过程较为复杂的表达式放在运算符的右侧以减少不必要的运算
三、算术运算符
1. 常见可用于整数和浮点数的二元运算符有 +
-
*
/
(Go 在进行字符串拼接时允许使用对运算符 +
的重载)
除法运算符 /
对于整数运算而言,结果依旧为整数:
9 / 4 -> 2
取余运算符 % 只能作用于整数:
9 % 4 -> 1
可以将语句 b = b + a
简写为 b+=a
,同样的写法也可用于 -=
*=
/=
%=(赋值运算符)
2. 对于整数和浮点数,可以使用一元运算符 ++
(递增)和 --
(递减),但只能用于后缀
同时,带有 ++
和 --
的只能作为语句,而非表达式,因此 n = i++
这种写法是无效的
i++ -> i += 1 -> i = i + 1
i-- -> i -= 1 -> i = i - 1
四、位运算符
位运算只能用于整数类型且类型长度相同的变量
一元位运算符: 按位补足^ 位左移<< 位右移>>
二元位运算符: 按位与& 按位异或^ 按位或| 位清除&^
1. 按位与 &:运算符查看两个表达式的二进制表示法的值,对应位置上的值经过和运算得出结果
package main
import "fmt"
func main() {
fmt.Printf("Val: %b",7 & 2) // Val:10
fmt.Println()
fmt.Printf("Val: %d",7 & 2) // Val:2
/*
运算过程:
7 & 2
111 & 010 // 转为二进制
010
-> 2
*/
}
%b
是用于位的格式化标识符,%d
用于格式化表示整数标识符
2. 按位或 |:运算符查看两个表达式的二进制表示法的值,对应位置上的值经过或运算得出结果
package main
import "fmt"
func main() {
fmt.Printf("Val: %b",7 | 2) // Val:111
fmt.Println()
fmt.Printf("Val: %d",7 | 2) // Val:7
/*
运算过程:
7 | 2
111 | 010 // 转为二进制
111
-> 7
*/
}
3. 按位异或 ^:运算符查看两个表达式的二进制表示法的值,当且仅当只有一个表达式的某位上为 1 时,结果的该位才为 1。否则结果的该位为 0
package main
import "fmt"
func main() {
fmt.Printf("Val: %b",7 ^ 2) // Val:101
fmt.Println()
fmt.Printf("Val: %d",7 ^ 2) // Val:5
/*
运算过程:
7 ^ 2
111 ^ 010 // 转为二进制
101
-> 5
*/
}
4. 位清除 &^: c = a &^ b 其中b 转为二进制时,值为1的位置对应c的位置值为0,c中剩余位置值与a对应位置值相同(把b中1对应位置在c位置上清0)
实际上就是进行先 取反 后 与& 的运算,即:
c = a &^ b
-> B = b取反
-> c = a & B
package main
import "fmt"
func main() {
fmt.Printf("Val: %b",6 &^ 11) // Val:100
fmt.Println()
fmt.Printf("Val: %d",6 &^ 11) // Val:4
/*
运算过程:
6 &^ 11
0110 &^ 1011 // 转为二进制
^1011 -> 0100 // 对11进行取反操作
0110 & 0100 // 取反后与6进行与运算
-> 0100
-> 4
*/
}
5. 位左移 << :位向左移动 n 位,右侧空白部分使用 0 填充。如果 n 等于 2,则结果是 2 的相应倍数,即 2 的 n 次方
package main
import "fmt"
func main() {
fmt.Printf("Val: %b",1 << 10) // Val: 10000000000
fmt.Println()
fmt.Printf("Val: %d",1 << 10) // Val: 1024
}
6. 位右移 >> : 位向右移动 n 位,左侧空白部分使用 0 填充;如果 n 等于 2,则结果是当前值除以 2 的 n 次方
package main
import "fmt"
func main() {
fmt.Printf("Val: %b",1024 >> 3) // Val: 10000000
fmt.Println()
fmt.Printf("Val: %d",1024 >> 3) // Val: 128
}
7. 按位补足 ^ (一元运算): 该运算符与异或运算符一同使用,即 m^x,对于无符号 x 使用 "全部位设置为 1",对于有符号 x 时使用 m=-1
package main
import "fmt"
func main() {
a := uint8(2) // 无符号整数
b := int8(2)
fmt.Printf("二进制表示: %b 整数表示: %d",^a,^a) // 二进制表示: 11111101 整数表示: 253
fmt.Println()
fmt.Printf("二进制表示: %b 整数表示: %d",^b,^b) // 二进制表示: -11 整数表示: -3
/*
运算过程:
^2 // 8位有符号整数
-> ^00000010 // 转二进制
-> -00000001 ^ 00000010
-> -00000011
-> -3
*/
}
五、其他运算符
& | 返回变量存储地址 | &a 将给出变量的实际地址。 |
* | 指针变量 | *a 是一个指针变量
|
<- | 在channel操作中表示据流动的方向 | a <- value |
package main
import "fmt"
func main() {
var a int = 4
var b int32
var c float32
var ptr *int
/* 运算符实例 */
fmt.Printf("第 1 行 - a 变量类型为 = %T\n", a );
fmt.Printf("第 2 行 - b 变量类型为 = %T\n", b );
fmt.Printf("第 3 行 - c 变量类型为 = %T\n", c );
/* & 和 * 运算符实例 */
ptr = &a /* 'ptr' 包含了 'a' 变量的地址 */
fmt.Printf("a 的值为 %d\n", a);
fmt.Printf("*ptr 为 %d\n", *ptr);
}
参考资料: