(文章目录)

逻辑运算符

与运算(&)

A B A&B
False False False
False True False
True False False
True True True

或运算(|)

A B A | B
False False False
False True True
True False True
True True True

非运算(!)

A !A
False True
True False

算数运算符

+、-、*、/、%、++、--.

  • +、-还可以当做正负用,就不是算数运算符了,例如 -s 。
  • ++、--只能是i++、i--,且是语句,不是表达式。也就是说,语句不能放到等式、函数参数等地方。例如, fmt.Println(a++) 是语法错误。Go语言没有++i、--i。

常量计算问题

常量分为typed类型化常量和untyped常量。

常量溢出

在进行整数常量计算时,如果结果超过了该类型所能表示的范围,就会发生常量溢出。例如下面的代码:

const a uint8 = 200 //uint8 无符号类型 取值范围[0,255]
const b = a + 100 // 常量溢出,编译报错

上述代码中,a 的类型为 uint8,表示的最大正整数是 255。而 a + 100 的结果为 300,超出了 uint8 能表示的范围,因此编译时会报错。

数据类型不同

GO是强类型语言,不同数据类型之间不能进行计算

var a int = 1
var b float32 = 2.3
fmt.Println(a * b) // 错误,int和float32类型不同,无法计算,除非强制类型转,Go语言中这种情况不会进行隐式类型转换


var a = 1 // 类型推导: int
var b = 2.3 // 类型推导: float64
fmt.Println(a * b) // 错误,int和float64类型不同,无法计算,除非强制类型转换

image.png ==上面的常量被赋给了变量,这些变量就确定了类型,虽然他们指向的值是字面常量,但是计算使用变量,但变量的类型不一致,报错。==

var a = 1 * 2.3             // 不报错
fmt.Printf("%T %v\n", a, a) // float64 2.3

image.png

==右边使用的都是字面常量,而字面常量都是无类型常量untyped constant,它会在上下文中隐式转换==

位运算符

按位与运算符(&)

两个相应的二进制位都为 1 时,结果才为 1。

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

按位或运算符(|)

两个相应的二进制位中只要有一个为 1 时,结果就是 1。

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

按位异或运算符(^)

两个相应的二进制位不同则结果为 1,否则为 0。

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

左移位运算符(<<)

把一个数的各二进制位全部左移若干位,高位丢弃,低位补 0。

var x  = 1       // 0000 0001
var y  = x << 1  // 0000 0010

右移位运算符(>>)

把一个数的各二进制位全部右移若干位,正号数左补 0,负号数左补 1。

var x  = 4      // 0000 0100
var y  = x >> 1 // 0000 0010

按位清空(&^ )

是一种按位清零的操作符。是先把右边按位取反后的值,再和左边位与,也就是右边有1的位的值不能保留,被清空,原 来是0的位被保留。换句话说,就是按照右边有1的位清空左边对应位

var a = 60  //0011 1100		0011 1100
var b = 18  //0001 0010		1110 1101
c := a &^ b //				0010 1100

比较运算符

==、!=、>、<、>=、<= 比较运算符组成的表达式,返回bool类型值。成立返回true,不成立返回false。

逻辑运算符

与运算符(&&)

当两个操作数都为 true 时,才返回 true,否则返回 false。

var a, b, c bool
a = true
b = false
c = a && b    // 返回 false

或运算符(||)

只要有一个操作数为 true,就返回 true,否则返回 false。

var a, b, c bool
a = true
b = false
c = a || b    // 返回 true

非运算符(!)

对一个操作数取反,如果原来为 true,则变成 false,如果原来为 false,则变成 true。

var a, b bool
a = true
b = !a    // 返回 false

==注意==:Go 语言中的逻辑运算符具有短路特性。这意味着当表达式的结果可以确定时,计算过程将立即停止。例如,对于表达式 a && b,如果 a 为 false,则不需要计算 b 的值,因为整个表达式的结果已经可以确定为 false。这种机制可以提高程序的效率。

赋值运算符

等号(=)

将右侧操作数的值赋给左侧操作数。

var i int
i = 42

加等于(+=)

将左侧操作数和右侧操作数的和赋给左侧操作数。

var i int
i += 3     // 相当于 i = i + 3

减等于(-=)

将左侧操作数减去右侧操作数的差赋给左侧操作数。

var i int
i -= 3     // 相当于 i = i - 3

乘等于(*=)

将左侧操作数和右侧操作数的积赋给左侧操作数。

var i int
i *= 3     // 相当于 i = i * 3

除等于(/=)

将左侧操作数除以右侧操作数的商赋给左侧操作数。

var i int
i /= 3     // 相当于 i = i / 3

取模等于(%=)

将左侧操作数除以右侧操作数的余数赋给左侧操作数。

var i int
i %= 3     // 相当于 i = i % 3

左移等于(<<=)

将左侧操作数左移右侧操作数指定的位数,并将结果赋给左侧操作数。

var i  = 4 // 0000 0100
i <<= 2    // 相当于 i = i << 2,即 0001 0000,即 16

右移等于(>>=)

将左侧操作数右移右侧操作数指定的位数,并将结果赋给左侧操作数。

var i  = 128 // 1000 0000
i >>= 3      // 相当于 i = i >> 3,即 0001 0000,即 16

按位与等于 &

将左侧操作数和右侧操作数进行按位与运算,并将结果赋给左侧操作数。

var a = 174 // 1010 1110
var b = 59 //  0011 1011

a &= b       // 等价于 a = a & b,即 00101010,即 42

按位异或等于 ^=

将左侧操作数和右侧操作数进行按位异或运算,并将结果赋给左侧操作数。

var a = 174 // 1010 1110
var b = 59 //  0011 1011

a ^= b       // 等价于 a = a ^ b,即 10010101,即 149

按位或等于 |=

将左侧操作数和右侧操作数进行按位或运算,并将结果赋给左侧操作数。

var a = 174 // 1010 1110
var b = 59 //  0011 1011

a |= b       // 等价于 a = a | b,即 10111111,即 191

==注意==赋值运算符的优先级较低,因此在使用复合赋值运算符时,要特别注意其结合顺序。例如,表达式 a += b * c 等价于 a = a + (b * c),而不是 a = (a + b) * c。建议在使用复合赋值运算符时,尽可能使用括号明确表达式的含义和结合顺序。

指针操作

数据是放在内存中,内存是线性编址的。任何数据在内存中都可以通过一个地址来找到它。

取地址操作符(&)

取地址操作符 & 可以返回一个变量的地址,并生成一个指向该变量的指针。 image.png

间接引用操作符(*)

间接引用操作符 * 可以返回一个指针所指向的变量的值。 image.png

image.png

==注意==:在 Go 语言中,指针不支持指针运算(如加减),也不支持随意转换为整数类型。另外,使用指针时,要特别注意指针的有效性,避免出现空指针异常。若需要使用 nil 指针,可以使用空指针常量 nil 来代替。

优先级

Category Operator Associativity
Postfix后缀 () [] -> . ++ - - Left to right
Unary单目 + - ! ~ ++ - - (type)* & sizeof Right to left
Multiplicative乘除 * / % Left to right
Additive加减 + - Left to right
Shift移位 << >> Left to right
Relational关系 < <= > >= Left to right
Equality相等 == != Left to right
Bitwise AND & Left to right
Bitwise XOR ^ Left to right
Bitwise OR | Left to right
Logical AND && Left to right
Logical OR || Left to right
Assignment赋值 = += -= *= /= %=>>= <<= &= ^= |= Right to left
Comma逗号运算符 , Left to right

规则:

  • 表中优先级由高到低
  • 单目 > 双目
  • 算数 > 移位 > 比较 > 逻辑 > 赋值
  • 搞不清,用括号,避免产生歧义

思考

15 & 5 和 15 &^ 5 有啥区别

15&5

15 1111
5  0101
   0101

15&^5

5  0101
   1010
15 1111
   1010

==总结==:

  • & 可以看做某位是1则该位保留其余位清除
  • &^可以看做某位是1则该位清除其余位保留