Golang 运算符
文章目录
- 0.概览
- 1.算数运算符
- 2.关系运算符
- 3.逻辑运算符
- 4.位运算符
- 5.赋值运算符
- 6.其他运算符
- 7.运算符优先级
- 8.小结
- 参考文献
0.概览
Go 语言内置运算符有:
- 算术运算符
- 关系运算符
- 逻辑运算符
- 位运算符
- 赋值运算符
1.算数运算符
运算符 | 说明 | 运算数要求 |
---|---|---|
+ | 加法 | 数值类型(整型、浮点型、复数)或字符串(仅拼接) |
- | 减法 | 数值类型(整型、浮点型、复数) |
* | 乘法 | 数值类型(整型、浮点型、复数) |
/ | 除法 | 数值类型(整型、浮点型、复数),除数不能为0 |
% | 取模(取余) | 仅限整型,除数不能为0 |
++ | 自增 | 数值类型变量(不能用于常量),不返回值(不能参与表达式) |
-- | 自减 | 数值类型变量(不能用于常量),不返回值(不能参与表达式) |
示例:
a := 10 % 3 // 合法(整型)
b := 5.0 / 2 // 合法(浮点型)
c := "Go" + "lang" // 合法(字符串拼接)
d := 10 / 0 // 非法(除数为0)
e := 5.2 % 3 // 非法(浮点型不能取模)
2.关系运算符
运算符 | 名称 | 运算数要求 |
---|---|---|
== | 等于 | 可比较类型(数值、字符串、布尔、指针、通道、接口、结构体/数组*) |
!= | 不等于 | 同 == |
> | 大于 | 数值类型或字符串(按字典序) |
< | 小于 | 同 > |
>= | 大于等于 | 同 > |
<= | 小于等于 | 同 > |
注意:
- 结构体和数组要求所有字段/元素可比较。
- 切片、map、函数不可比较(只能与 nil 比较)。
示例:
fmt.Println(3 > 2) // true(数值)
fmt.Println("abc" < "def") // true(字符串字典序)
var s []int
fmt.Println(s == nil) // true(切片可与nil比较)
fmt.Println([]int{1} == []int{1}) // 非法(切片不能直接比较)
3.逻辑运算符
运算符 | 名称 | 运算数要求 |
---|---|---|
&& | 逻辑与 | 布尔类型(true/false) |
|| | 逻辑或 | 同 && |
! | 逻辑非 | 同 &&(单目运算符) |
示例:
fmt.Println(true && false) // false
fmt.Println(!(5 > 3)) // false(需先通过比较得到布尔值)
fmt.Println(1 && 0) // 非法(非布尔类型)
4.位运算符
运算符 | 名称 | 运算数要求 |
---|---|---|
& | 按位与 | 仅限整型 |
| | 按位或 | 同 & |
^ | 按位异或 | 同 &(或单目取反) |
&^ | 按位清除 | 同 & |
<< | 左移位 | 左操作数整型,右操作数无符号整型 |
>> | 右移位 | 同 << |
移位规则:
- 左移:低位补0
- 右移:
- 无符号整型:高位补0
- 有符号整型:高位补符号位(算术右移)
特殊的位运算符:
&^
m &^ n
等价于m & (^n)
。
&^
是 Golang 中特有的一个位运算符,作用是按位清除 (Bit Clear),将左操作数中,对应右操作数位为1的位置清零。
^
^
既是是双目运算符,也是单目运算符。
双目运算符为异或运算,单目运算符为按位取反。其他编程语言按位取反的运算符一般为 ~
。
示例:
a := 6 &^ 3 // 按位清除:0110 &^ 0011 = 0100 (4)
b := 1 << 3 // 8(左移3位)
c := -8 >> 2 // -2(算术右移)
d := 3.5 << 2 // 非法(浮点型不能移位)fmt.Printf("%b", ^uint8(2)) // 按位取反,输出 11111101
5.赋值运算符
运算符 | 说明 | 等价形式 | 运算数要求 |
---|---|---|---|
= | 基本赋值 | - | 左值必须为变量(类型匹配) |
+= | 加后赋值 | a = a + b | 支持算术/位运算对应的类型 |
-= | 减后赋值 | a = a - b | 同 += |
*= | 乘后赋值 | a = a * b | 同 += |
/= | 除后赋值 | a = a / b | 同 += |
%= | 取模后赋值 | a = a % b | 仅整型 |
&= | 按位与后赋值 | a = a & b | 同 %= |
|= | 按位或后赋值 | a = a | b | 同 %= |
^= | 按位异或后赋值 | a = a ^ b | 同 %= |
<<= | 左移后赋值 | a = a << b | 左操作数整型,右操作数无符号整型 |
>>= | 右移后赋值 | a = a >> b | 同 <<= |
示例:
var x int
x += 5 // 合法(算术运算)
y := 10
y &= 3 // 合法(位运算)
var f float64
f %= 2 // 非法(浮点型不能取模)
6.其他运算符
在 Go 语言中,除了之前提到的五类主要运算符,还有一些重要的特殊运算符,它们提供了底层内存操作、类型处理、通道控制等核心功能。
运算符 | 名称 | 说明 | 运算数要求 |
---|---|---|---|
& | 取地址 | 返回变量的内存地址 | 必须是可寻址的值(变量、切片元素、结构体字段等),常量、字面量、函数返回值不可用。 |
* | 解引用 | 访问指针指向的值 | 必须是指针类型 |
<- | 通道操作 | 1. 发送值到通道。 2. 从通道接收值 | 1. 左侧必须是通道,右侧值类型需匹配通道类型。 2. 必须是通道类型。 |
: | 切片/数组 | 创建切片或截取子数组 | 数组/切片 + 索引(可选) |
.(T) | 类型断言 | 1. 检查接口值的实际类型 2. 将接口值转换为具体类型 | 必须是接口类型 |
... | 可变参数 | 1. 函数参数:表示可变参数 2. 切片展开:将切片元素作为独立参数传入 | 1. 函数参数列表 2. 切片类型 |
, | 逗号操作符 | 1. 多变量声明/赋值 2. 多返回值处理 3. 忽略返回值 | 无特殊限制 |
: | 标签 | 标记代码位置(用于 break/continue/goto) | 必须与 break/continue/goto 配合使用 |
{} | 复合字面量 | 初始化结构体、数组、切片、map | 类型 + 初始化值 |
示例:
// &
x := 10
p := &x // p 是指向 x 的指针
py := &10 // 错误:字面量不可寻址
pf := &fmt.Println // 错误:函数不可寻址// *
fmt.Println(*p) // 输出 10// <-
ch <- data // 发送
data := <-ch // 接收// :
s := arr[1:4] // 截取索引1-3// .(T)
str := val.(string) // 断言为string// ...
func sum(nums ...int){}
sum(slice...)// ,
a, b := 1, 2
_, err := func()
for i, v := range slice// :
loop: for {... break loop}// {}
p := Point{X: 1, Y: 2}
m := map[string]int{"a": 1}
7.运算符优先级
运算符优先级确定表达式中的分组。这会影响表达式的计算方式。
在 Go 语言中,一元运算符(一些只需要一个操作数的运算符称为一元运算符(或单目运算符)。)拥有最高的优先级,二元运算符的运算方向均是从左至右。
当表达式包含多种运算符时,按以下优先级执行(从高到低):
优先级 | 运算符 | 说明 | 结合性 |
---|---|---|---|
1 | () [] {} . | 函数调用 数组索引 复合字面量 选择器(结构体字段) | 从左到右 |
2 | ++ -- + - ! ^ * & <- | 自增/自减 正号/负号 逻辑非 按位取反 解引用 取地址 接收操作符 | 从右到左 |
3 | * / % << >> & &^ | 乘法/除法/取模 位左移/右移 按位与 按位清除 | 从左到右 |
4 | + - | ^ | 加法/减法 按位或 按位异或 | 从左到右 |
5 | == != < <= > >= | 关系运算符 | 从左到右 |
6 | && | 逻辑与 | 从左到右 |
7 | || | 逻辑或 | 从左到右 |
8 | <- | 发送操作符 | 从右到左 |
9 | = += -= *= /= %= <<= >>= &= ^= &^= | 赋值运算符 | 从右到左 |
记忆口诀:单目 > 算术 > 移位 > 关系 > 逻辑 > 赋值。
记住:当有疑问时,使用括号明确运算顺序,这既能保证正确性,也能提高代码可读性。
8.小结
Golang 的运算符设计体现了简洁性、实用性与安全性,主要有如下特点:
- 类型安全:严格限制运算数类型,混合类型需显式转换。
a := int32(5) + int64(10) // 非法!需统一类型
- 零值安全:变量声明自动初始化零值,但除数为 0 会 panic。
- 不可比较类型:切片、map、函数只能与 nil 比较。
- 移位限制:移位右操作数必须为无符号整型。
- 自增/自减:只能独立使用(i++ 合法,j = i++ 非法)。
- 指针访问:统一使用 .(自动解引用),没有 -> 运算符。
- 接口类型断言:必须使用
.(T)
语法,建议用安全形式:val, ok := interfaceVar.(Type)
。 - 通道操作:
<-
既用于发送也用于接收,根据位置区分。 - 字符串拼接:+ 支持字符串拼接,效率低时用
strings.Builder
。 - 运算符优先级:明确分级,括号优先。
Go 的运算符设计体现了 “显式优于隐式” 的哲学,通过掌握这些运算符的特性和最佳实践,可以编写出更高效、更安全的 Go 代码。
参考文献
The Go Programming Language Specification