Go 编程实战系列(十六)
上一篇《Go 输入输出详解》中,我们学习了如何从键盘读取数据,以及如何把程序结果输出到终端。本篇继续学习 Go 基础语法中的另一个重要知识点:运算符。
运算符用于对变量和值进行计算、比较和逻辑判断。例如:
css
a + b
age >= 18
isLogin && isAdmin
count += 1
这些都属于运算符的使用。
在实际开发中,运算符几乎无处不在,例如商品金额计算、权限判断、分页计算、状态处理、位标记等。本文将系统介绍 Go 中常用的运算符,包括:
-
算术运算符
-
比较运算符
-
逻辑运算符
-
赋值运算符
-
自增与自减
-
位运算符
-
运算符优先级
-
常见错误与实战案例
一、什么是运算符?
运算符就是用于操作数据的符号。
例如:
go
a := 10
b := 20
result := a + b
这里的:
diff
+
就是运算符。
而:
css
a
b
叫作操作数。
表达式:
css
a + b
表示把两个值相加。
Go 中的运算符大体可以分为:
算术运算符
比较运算符
逻辑运算符
赋值运算符
位运算符
不同运算符适用于不同的数据类型和场景。
二、算术运算符
算术运算符主要用于数字计算。
Go 中常见的算术运算符有:
| 运算符 | 作用 |
|---|---|
| + | 加法 |
| - | 减法 |
| * | 乘法 |
| / | 除法 |
| % | 取余 |
例如:
css
package main
import "fmt"
func main() {
a := 10
b := 3
fmt.Println(a + b)
fmt.Println(a - b)
fmt.Println(a * b)
fmt.Println(a / b)
fmt.Println(a % b)
}
输出:
13
7
30
3
1
三、加法运算符 +
最简单的用法:
go
a := 10
b := 20
result := a + b
结果:
30
+ 还可以用于字符串拼接:
sql
first := "Hello"
second := "Go"
result := first + " " + second
fmt.Println(result)
输出:
Hello Go
但是不同类型不能直接相加。
错误:
go
age := 20
text := "年龄:" + age
因为:
c
string
和:
arduino
int
类型不同。
需要转换:
scss
text := "年龄:" + strconv.Itoa(age)
四、减法和乘法
减法:
go
price := 100
discount := 20
result := price - discount
fmt.Println(result)
输出:
80
乘法:
go
price := 20
count := 3
total := price * count
fmt.Println(total)
输出:
60
这类运算在订单计算、库存计算中非常常见。
五、除法运算
除法使用:
/
例如:
css
a := 10
b := 2
fmt.Println(a / b)
输出:
5
但是整数除法需要特别注意。
例如:
css
a := 10
b := 3
fmt.Println(a / b)
结果:
3
不是:
3.333333
因为:
arduino
int / int
结果仍然是:
arduino
int
如果需要小数:
css
result := float64(a) / float64(b)
fmt.Println(result)
结果:
3.3333333333333335
六、取余运算 %
取余就是获取除法后的余数。
例如:
scss
fmt.Println(10 % 3)
结果:
1
取余经常用于判断奇偶数。
例如:
dart
num := 10
if num%2 == 0 {
fmt.Println("偶数")
}
输出:
偶数
判断奇数:
perl
if num%2 != 0 {
fmt.Println("奇数")
}
分页、循环、轮询任务中也经常使用 %。
七、比较运算符
比较运算符用于比较两个值,结果一定是:
arduino
bool
也就是:
arduino
true
false
常见比较运算符:
| 运算符 | 作用 |
|---|---|
| == | 等于 |
| != | 不等于 |
| 大于 | |
| < | 小于 |
| >= | 大于等于 |
| <= | 小于等于 |
例如:
css
age := 20
fmt.Println(age == 20)
fmt.Println(age != 18)
fmt.Println(age > 18)
fmt.Println(age < 30)
fmt.Println(age >= 20)
fmt.Println(age <= 20)
输出:
arduino
true
true
true
true
true
true
八、== 和 = 的区别
这是初学者非常容易混淆的地方。
=
表示赋值。
例如:
ini
age = 20
表示把 20 赋给 age。
而:
==
表示比较。
例如:
ini
age == 20
判断 age 是否等于 20。
两者含义完全不同。
九、逻辑运算符
逻辑运算符主要用于多个条件组合。
Go 提供:
diff
&&
||
!
分别表示:
并且
或者
取反
十、&& 逻辑与
只有两个条件都成立,结果才是 true。
例如:
go
age := 20
hasID := true
if age >= 18 && hasID {
fmt.Println("允许进入")
}
这里要求:
年龄大于等于18
并且
有证件
两个条件必须都成立。
逻辑关系:
arduino
true && true = true
true && false = false
false && true = false
false && false = false
十一、|| 逻辑或
只要一个条件成立,结果就是 true。
例如:
go
isAdmin := false
isManager := true
if isAdmin || isManager {
fmt.Println("允许访问后台")
}
因为 isManager 为 true,所以整体条件成立。
逻辑关系:
arduino
true || true = true
true || false = true
false || true = true
false || false = false
十二、! 逻辑非
! 表示取反。
例如:
go
isLogin := false
fmt.Println(!isLogin)
输出:
arduino
true
实际开发中:
arduino
if !isLogin {
fmt.Println("请先登录")
}
比:
ini
if isLogin == false {
}
更加简洁。
十三、逻辑运算的短路特性
Go 的 && 和 || 支持短路。
例如:
scss
false && check()
因为第一个条件已经是 false,所以结果一定是 false,check() 不会执行。
而:
scss
true || check()
第一个条件已经为 true,所以 check() 同样不会执行。
这在实际开发中非常重要。
例如:
go
if user != nil && user.Name != "" {
fmt.Println(user.Name)
}
如果:
ini
user == nil
那么后面的:
user.Name
不会执行,可以避免空指针问题。
十四、赋值运算符
最基本的赋值运算符:
=
例如:
ini
age := 18
age = 20
Go 还提供复合赋值运算符。
例如:
markdown
+=
-=
*=
/=
%=
例如:
makefile
count := 10
count += 5
等价:
ini
count = count + 5
结果:
15
其他写法:
ini
count -= 2
count *= 3
count /= 2
count %= 5
复合赋值在计数器、金额累计等场景中非常常见。
十五、自增和自减
Go 支持:
markdown
++
--
例如:
css
count := 10
count++
fmt.Println(count)
输出:
11
自减:
lua
count--
结果减少 1。
需要特别注意:
Go 中 ++ 和 -- 是语句,不是表达式。
因此不能这样写:
css
a := count++
这是错误的。
也不能:
diff
++count
Go 只支持:
lua
count++
count--
这一点和 C、Java 等语言不同。
十六、位运算符
Go 还提供位运算。
常见运算符:
| 运算符 | 作用 |
|------|------|-----|
| & | 按位与 |
| | | 按位或 |
| | 按位异或 |
| &^ | 位清除 |
| << | 左移 |
| >> | 右移 |
位运算主要处理整数的二进制位。
例如:
css
a := 6
b := 3
fmt.Println(a & b)
二进制:
ini
6 = 110
3 = 011
按位与:
yaml
110
011
---
010
结果:
2
十七、按位或 |
例如:
scss
fmt.Println(6 | 3)
二进制:
yaml
110
011
---
111
结果:
7
位运算经常用于:
-
权限标志
-
状态位
-
网络协议
-
底层开发
普通 Web 业务使用相对较少,但理解其基本原理仍然很重要。
十八、左移和右移
左移:
dart
num := 1
fmt.Println(num << 1)
结果:
2
因为:
yaml
0001
左移一位:
0010
再例如:
bash
1 << 3
结果:
8
右移:
8 >> 1
结果:
4
在二进制计算和性能敏感场景中比较常见。
十九、运算符优先级
复杂表达式中,不同运算符存在执行顺序。
例如:
go
result := 10 + 2*3
结果:
16
因为乘法优先于加法。
如果希望先计算加法:
go
result := (10 + 2) * 3
结果:
36
实际开发中,不建议过度记忆全部优先级。
当表达式较复杂时,推荐直接使用括号:
go
result := (a + b) * c
比依赖运算符优先级更加清晰。
二十、运算符实际案例:订单金额
例如:
go
package main
import "fmt"
func main() {
price := 100
count := 3
discount := 20
total := price*count - discount
fmt.Println("订单金额:", total)
}
输出:
订单金额: 280
这里使用了:
markdown
*
-
两个算术运算符。
二十一、实际案例:用户登录判断
go
package main
import "fmt"
func main() {
usernameOK := true
passwordOK := true
disabled := false
if usernameOK && passwordOK && !disabled {
fmt.Println("登录成功")
}
}
这里使用:
diff
&&
!
组合多个业务条件。
二十二、实际案例:分页计算
假设:
go
total := 101
pageSize := 10
计算总页数:
css
pages := total / pageSize
if total%pageSize != 0 {
pages++
}
最终:
11页
这里综合使用:
diff
/
%
!=
++
这类计算在 Web 后台分页中非常常见。
二十三、常见错误
1. 不同数字类型直接运算
错误:
css
var a int = 10
var b int64 = 20
fmt.Println(a + b)
需要:
css
fmt.Println(int64(a) + b)
2. 整数除法误以为有小数
scss
fmt.Println(5 / 2)
结果:
2
需要:
go
fmt.Println(float64(5) / 2)
3. 把赋值写成比较
错误理解:
ini
age = 18
这是赋值。
比较应该使用:
ini
age == 18
4. 把 & 和 && 混淆
&
是位运算。
&&
是逻辑运算。
例如条件判断应该写:
css
if a > 0 && b > 0 {
}
而不是:
css
if a > 0 & b > 0 {
}
二十四、本章小结
本篇介绍了 Go 中常见的运算符,主要包括:
diff
算术运算:
+ - * / %
比较运算:
== != > < >= <=
逻辑运算:
&& || !
赋值运算:
= += -= *= /= %=
自增自减:
++ --
位运算:
& | ^ &^ << >>
需要重点记住几个容易出错的地方:
- 整数相除结果仍然是整数;
- 不同数字类型不能直接运算;
=是赋值,==是比较;&&和||支持短路;- Go 中
++和--只能作为独立语句使用; - 复杂表达式推荐使用括号提高可读性。
掌握运算符之后,我们已经具备编写各种条件表达式的基础,下一步就可以正式学习 Go 的流程控制。
本章练习
- 输入两个整数,分别计算加、减、乘、除和取余。
- 判断一个整数是奇数还是偶数。
- 判断用户年龄是否大于等于 18。
- 使用
&&判断用户名和密码是否都正确。 - 使用
||判断用户是否为管理员或经理。 - 使用
+=实现一个累加器。 - 使用
<<计算 2 的不同次方。 - 编写一个订单金额计算程序。
- 编写分页总页数计算程序。
下一篇预告
《Go if 判断详解》
下一篇将正式进入 Go 流程控制,详细介绍:
-
if基本语法; -
if else; -
else if; -
多条件判断;
-
嵌套 if;
-
if 初始化语句;
-
变量作用域;
-
提前 return;
-
实际业务判断案例。
掌握 if 后,我们就可以根据不同条件控制程序执行不同的代码逻辑。