golang控制语句和运算符
流程控制是每种编程语言控制逻辑走向和执行次序的重要手段,Go语言中最常用的流程控制有 if
、for
。
而 switch
、goto
主要是为了简化代码、降低重复代码而生的结构,属于扩展的流程控制。
一、if else语句(分支结构)
1、if条件判断基本写法
Go 语言中 if 语句的基本写法如下:
if 条件表达式1 {
分支1
} else if 条件表达式2 {
分支2
} else {
分支3
}
当表达式1的结果为 true 时,执行分支1,否则判断表达式2,如果满足则执行分支2,都不满足时,则执行分支3。
if 语句中的 else if 和 else 都是可选的,可以根据实际需要进行选择。
Go 语言规定与 if 匹配的左括号 {
必须与 if 和表达式放在同一行,{
放在其他位置会触发编译错误。示例如下:
func ifDemo1() {
score := 65
if score >= 90 {
fmt.Println("A")
} else if score >= 80 {
fmt.Println("B")
} else if score >= 70 {
fmt.Println("C")
}
}
2、if条件判断特殊写法
if 还有一种特殊的写法,可以在 if 表达式之前添加一个执行语句,再根据变量值进行判断。示例如下:
func ifDemo1() {
if score := 65; score >= 90 {
fmt.Println("A")
} else if score >= 80 {
fmt.Println("B")
} else if score >= 70 {
fmt.Println("C")
}
// if 语句中的变量 score 的作用域只在 if 条件判断语句中
// score 变量定义后,可以在 if 条件判断语句中使用,但是在 if 语句外部无法使用。
fmt.Println(score) // undefined: score
}
这种写法只有在 if 表达式中定义的变量才可以在 if 分支语句中使用,其他地方就不可以使用了。
二、for循环结构
Go 语言中的所有循环类型均可以使用 for
关键字来完成。
1、for循环基本写法
for 循环的基本格式如下:
for 初始语句;条件表达式;结束语句 {
循环体语句
}
// 示例
func forDemo1() {
for i := 0; i < 10; i++ {
fmt.Println(i)
}
}
条件表达式返回 true
时循环体不停地循环,直到条件表达式返回 false
时自动退出循环。
2、for循环省略初始语句
for 循环的初始语句可以被忽略,但是初始语句后的分号必须要写,例如:
func forDemo2() {
i := 0
for ; i < 10; i++ {
fmt.Println(i)
}
}
3、for循环省略初始语句和结束语句
for 循环的初始语句和结束语句都可以省略,例如:
func forDemo3() {
i := 0
for i < 10 {
fmt.Println(i)
i++
}
}
4、无限循环
如果省略循环条件,该循环就不会结束,因此可以用其他方式来结束无限循环,例如使用 break
语句跳出循环。
func forDemo4() {
for {
fmt.Println("无限循环")
}
}
for 循环还可以通过 break
、goto
、return
、panic
语句强制退出循环。
5、for range循环
Go 语言中可以使用 for range
遍历数组、切片、字符串、map 及通道(channel)。通过 for range
遍历的返回值有以下规律:
- 数组、切片、字符串返回索引和值。
- map 返回键和值。
- 通道(channel)只返回通道内的值。
// 数组、切片、字符串
for index, value := range slice1 {
fmt.Println(index, value)
}
// map
for key, value := range map1 {
fmt.Println(key, value)
}
// 通道(channel)
for value := range channel1 {
fmt.Println(value)
}
6、continue
在for循环中,当循环遇到continue关键字时,会停止当前循环,开始下一次循环。
func continueDemo1() {
for i := 0; i < 5; i++ {
if i == 3 {
continue // 跳过本次循环,继续下一次循环
}
fmt.Println(i)
}
}
/* Output:
0
1
2
4
*/
// 案例:使用循环输出 1 2 3 4 5 6 8 9 10,即:10以内除7以外的整数。
func continueDemo2() {
for i := 1; i <= 10; i++ {
if i == 7 {
continue
}
fmt.Println(i)
}
}
(1)for循环嵌套
for循环中还可以嵌套for循环,例如:
func continueDemo3() {
for i := 1; i < 3; i++ {
// i=1
// i=2
for j := 1; j < 5; j++ {
// j=1/2/3/4
fmt.Println(i, j)
}
}
}
>>> 输出:
1 1
1 2
1 3
1 4
2 1
2 2
2 3
2 4
(2)for循环嵌套 + continue
for循环嵌套 + continue,例如:
func continueDemo4() {
for i := 1; i < 3; i++ {
// i=1
// i=2
for j := 1; j < 5; j++ {
// j=1/2/3/4
if j == 3 {
continue
}
fmt.Println(i, j)
}
}
}
>>> 输出:
1 1
1 2
1 4
2 1
2 2
2 4
7、break
在for循环中时,循环中一旦遇到break,跳出循环。
for{
fmt.Println("王老汉、李老汉、张老汉")
break
fmt.Println("alex老婆满身大汗")
}
案例1:猜数字,设定一个理想数字比如:66,一直提示让用户输入数字,如果比66大,则显示猜测的结果大了;如果比66小,则显示猜测的结果小了;只有输入等于66,显示猜测结果正确,然后退出循环。
fmt.Print("开始")
data := 66
for{
var userInputNumber int
fmt.Print("请输入数字:")
fmt.Scanln(&userInputNumber)
if userInputNumber > data {
fmt.Println("大了")
} else if userInputNumber < data {
fmt.Println("小了")
} else {
fmt.Println("恭喜你猜对了")
break
}
}
fmt.Print("结束")
案例2:
for i:=1;i<3;i++{
// i=1
// i=2
for j:=1;j<5;j++{
// j=1/2/3/4
if j == 3{
break
}
fmt.Println(i,j)
}
}
>>> 输出:
1 1
1 2
2 1
2 2
for i:=1;i<3;i++{
// i=1
// i=2
for j:=1;j<5;j++{
// j=1/2/3/4
if j == 3{
break
}
fmt.Println(i,j)
}
break
}
>>> 输出:
1 1
1 2
对for进行打标签,然后通过break和continue就可以实现多层循环的跳出和终止。
f1:
for i := 1; i < 3; i++ {
// i=1
// i=2
for j := 1; j < 5; j++ {
// j=1/2/3/4
if j == 3 {
continue f1
}
fmt.Println(i, j)
}
}
>>> 输出:
1 1
1 2
2 1
2 2
f1:
for i := 1; i < 3; i++ {
// i=1
// i=2
for j := 1; j < 5; j++ {
// j=1/2/3/4
if j == 3 {
break f1
}
fmt.Println(i, j)
}
}
>>> 输出:
1 1
1 2
三、switch case语句
使用 switch
语句可方便地对大量的值进行条件判断。减少代码量。
func switchDemo1() {
finger := 3
switch finger {
case 1:
fmt.Println("大拇指")
case 2:
fmt.Println("食指")
case 3:
fmt.Println("中指")
case 4:
fmt.Println("无名指")
case 5:
fmt.Println("小拇指")
default: // 默认情况
fmt.Println("无效的输入!")
}
}
/* Output:
中指
*/
1、case后面可以带多个值
case 一次可以判断多个值,使用逗号分隔。
func switchDemo2() {
num := 5
switch num {
case 1, 3, 5, 7, 9:
fmt.Println("奇数")
case 2, 4, 6, 8, 10:
fmt.Println("偶数")
}
}
/* Output:
奇数
*/
2、case使用表达式
分支可以使用表达式,这时候switch语句后面不需要再跟判断变量。
func switchDemo3() {
age := 30
switch {
case age > 18:
fmt.Println("成年人")
case age < 18:
fmt.Println("未成年人")
default:
fmt.Println("未知")
}
}
/* Output:
成年人
*/
四、goto语句
goto
语句通过标签进行代码间的无条件跳转。
goto
语句可以在快速跳出循环、避免重复退出上有一定的帮助。
Go语言中使用goto
语句能简化一些代码的实现过程。例如双层嵌套的for循环要退出时:
func gotoDemo1() {
// 使用goto语句跳出多层for循环
for i := 0; i < 10; i++ {
for j := 0; j < 10; j++ {
if j == 2 {
// 设置退出标签
goto breakTag
}
fmt.Printf("%v-%v\n", i, j)
}
}
return
// 标签
breakTag:
fmt.Println("结束for循环")
}
/* Output:
0-0
0-1
结束for循环
*/
五、字符串格式化
将数据格式化成为特定格式的字符串时,可以使用字符串格式化。
package main
import "fmt"
func main() {
var name, address, action string
fmt.Print("请输入姓名:")
fmt.Scanln(&name)
fmt.Print("请输入位置:")
fmt.Scanln(&address)
fmt.Print("请输入行为:")
fmt.Scanln(&action)
result := fmt.Sprintf("我叫%s,在%s正在干%s", name, address, action)
//result := "我叫" + name + "在" + address + "干" + action
fmt.Println(result)
}
六、运算符
Go语言内置的运算符有:算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符、其他运算符。
1、算术运算符
(1)加减乘除求余
// Go语言中的运算符
func main() {
// 1.算术运算符
a := 10
b := 20
fmt.Println(a + b) // 30
fmt.Println(a - b) // -10
fmt.Println(a * b) // 200
fmt.Println(a / 3) // 3
fmt.Println(a % 3) // 1
}
(2)自增自减
++
和 --
在 Go 语言中时单独的语句,不能被赋值给其他变量使用。
Goyu语言中没有++i
和--i
。原因是Go语言中没有前置++
和--
,只有后置++
和--
。
package main
import "fmt"
func main() {
var i int = 1
var j int = 1
i++
j--
fmt.Println(i, j) // 2, 0
// ++i // Go语言中没有++i和--i
}
2、关系运算符
func main() {
fmt.Println(10 > 2) // true
fmt.Println(10 != 2) // true
fmt.Println(4 <= 3) // false
}
3、逻辑运算符
func main() {
// && 与运算符,两边都为真才为真
fmt.Println(10 > 2 && 10 < 2) // false
fmt.Println(10 > 5 && 3 == 3) // true
// || 或运算符,两边都为假才为假
fmt.Println(10 > 2 || 10 < 2) // true
fmt.Println(10 > 12 || 3 == 4) // false
// ! 非运算符,取反
fmt.Println(!(10 > 2)) // false
fmt.Println(!(10 < 2)) // true
}
4、位运算符
位运算符对整数在内存中的二进制位进行操作。
常见示例:
func main() {
a := 1 // 0001
b := 5 // 0101
// 按位与运算符
fmt.Println(a & b) // 0001 => 1
// 按位或运算符
fmt.Println(a | b) // 0101 => 5
// 按位异或运算符
fmt.Println(a ^ b) // 0100 => 4
// 按位左移运算符
fmt.Println(a << 2) // 0100 => 4
// 按位右移运算符
fmt.Println(a >> 2) // 0000 => 0
}
(1)位运算符必知必会概念
-
计算机中的 存储、运算、网络传输等任何的行为,本质上都是二进制的操作。例如:01010101。
A B hello -> 0101010010101 -> hello
-
信息表现形式
二进制表示:0101010010101 -> hello 十进制表示:1921 -> hello
-
十进制和二进制的转换关系
十进制 二进制 0 0 1 1 2 10 3 11 4 100 5 101 6 110 7 111 8 1000 9 1001 10 1010 ... ... -
二进制转换为十进制
10101 -> 2**4 + 2**2 + 2**0 => 16 + 4 + 1 => 21 101010010101 -> 2**11 + 2**9 + ....
-
十进制转换成二进制
99 -> 64 + 32 + 2 + 1 -> 2**6 + 2**5 + 2**1 + 2*0 -> 1100011
-
(2)位运算
位运算指的是二进制之间的运算:
// 1.按位进行与运算(全为1,才得1)
r1 := 5 & 99
5 -> 0000101
99 -> 1100011
0000001 -> 1
// 2.按位进行或运算(只要有1,就得1)
r2 := 5 | 99
5 -> 0000101
99 -> 1100011
1100111 -> 2**6 + 2**5 + 2**2 + 2**1 + 2**0 = 64 + 32 + 4 + 2 + 1 = 103
// 3.按位进行异或运算(上下不同,就得1)
r3 := 5 ^ 99
5 -> 0000101
99 -> 1100011
1100110 -> 2**6 + 2**5 + 2**2 + 2**1 = 64 + 32 + 4 + 2 = 102
// 4.按位向左移动
r4 := 5 << 2
5 -> 101
向左移动2位 -> 10100 -> 2**4 + 2**2 = 16 + 4 = 20
// 5.按位向右移动
r5 := 5 >> 1
5 -> 101
向右移动1位 -> 10 -> 2**1 = 2
// 6.比较清除 // 以前面的值为基准,让前面的和后面的值的二进制位进行比较,如果两个位置都是1,则讲前面的值的那个位置置0
r6 := 5 &^ 99
5 -> 0000101
99 -> 1100011
0000100 -> 2**2 = 4
5、赋值运算符
赋值运算符案例:
func main() {
// 赋值运算符
// += -= *= /= %= <<= >>= &= |= ^=
var a int = 5
a += 5 // a = a + 5
fmt.Println(a) // 10
var b int = 5 // 101
// 左移2位赋值给b
b <<= 2 // 10100 => 20
fmt.Println(b) // 20
// 按位与后赋值
var c int = 5 // 101
c &= 3 // 101 & 011 => 001 => 1
fmt.Println(c)
}
6、运算符的优先级
Precedence Operator
5 * / % << >> & &^
4 + - | ^
3 == != < <= > >=
2 &&
1 ||
v1 := 3 + 2 * 2
v2 := 8 == 5 & 99
注意:不要想办法去记住他,使用括号。
参考地址:
叮嘱:不要太过于用心去背、记,主要认识即可。优先级记不住就用括号。
今日作业
- 猜年龄游戏,要求:允许用户最多尝试3次,3次都没猜对的话,就直接退出,如果猜对了,打印恭喜信息并退出。
- 实现用户登录系统,并且要支持连续3次输错之后直接退出,并且在每次输错误时显示剩余错误次数(提示:使⽤字符串格式化)。