(文章目录)
逻辑运算符
与运算(&)
| 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类型不同,无法计算,除非强制类型转换
==上面的常量被赋给了变量,这些变量就确定了类型,虽然他们指向的值是字面常量,但是计算使用变量,但变量的类型不一致,报错。==
var a = 1 * 2.3             // 不报错
fmt.Printf("%T %v\n", a, a) // float64 2.3

==右边使用的都是字面常量,而字面常量都是无类型常量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。建议在使用复合赋值运算符时,尽可能使用括号明确表达式的含义和结合顺序。
指针操作
数据是放在内存中,内存是线性编址的。任何数据在内存中都可以通过一个地址来找到它。
取地址操作符(&)
取地址操作符 & 可以返回一个变量的地址,并生成一个指向该变量的指针。

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


==注意==:在 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则该位清除其余位保留
 










