12.流程控制#

通常我们需要代码在满足一定条件时候进行执行,或者需要重复执行代码,此时条件语句(if-else if -else)或者选择语句(swicth case)及循环语句(for)

!!! note

老婆给老公打电话,下班顺路买十个包子,如果看到买西瓜的,买一个。当晚老公拿着一个包子回家。老婆问道:你怎么只买了一个包子?老公回答:因为我看到卖西瓜的了。

if else#

老婆的想法,如果看到买西瓜的,买一个西瓜,代码:

package main
import "fmt"
func main(){
    fmt.Print("老婆的想法:")
    fmt.Println("买10个包子")

    var yes string
    fmt.Print("是否有卖西瓜的?")
    fmt.Scan(&yes)
    if yes == "Y"|| yes == "y" {
        fmt.Println("买一个西瓜")
    }
}

看到卖西瓜的,买一个西瓜,运行:

[root@marksugar /opt/Golang]# go run if1.go 
老婆的想法:买10个包子
是否看到卖西瓜的?y
买一个西瓜

如果没看到就买10个包子:

[root@marksugar /opt/Golang]# go run if1.go
老婆的想法:买10个包子
是否看到卖西瓜的?n

老公的想法是,如果看到买西瓜的,就买一个包子,否则就买10个包子。代码如下:

package main
import "fmt"
func main(){
    fmt.Print("老婆的想法:")
    fmt.Println("买10个包子")

    var yes string
    fmt.Print("是否看到卖西瓜的?")
    fmt.Scan(&yes)
    if yes == "Y"|| yes == "y" {
        fmt.Println("买一个西瓜")
    }
    fmt.Print("老公的想法:")
    if yes == "y"|| yes == "Y" {
        fmt.Println("买一个包子")
    }else {
        fmt.Println("买10个包子")
    }
}

如果看到了买西瓜的,买一个包子:

[root@marksugar /opt/Golang]# go run if1.go
老婆的想法:买10个包子
是否看到卖西瓜的?y
买一个西瓜
老公的想法:买一个包子

如果没看到,就买10个包子:

[root@marksugar /opt/Golang]# go run if1.go
老婆的想法:买10个包子
是否看到卖西瓜的?n
老公的想法:买10个包子

if else if#

如果输入大于等于90就打印A,大于等于80打印B,大于等于70打印C,大于等于60打印D,小于60就打印D-不及格。如下

    var score int
    fmt.Print("请输入成绩:")
    fmt.Scan(&score)
    if score >= 90 {
        fmt.Println("A")
    } else if score >= 80 {
        fmt.Println("B")
    } else if score >= 70 {
        fmt.Println("C")
    } else if score >= 60 {
        fmt.Println("D")
    } else {
        fmt.Println("D-,不及格")
    }

运行

[root@marksugar /opt/Golang]# go run if1.go
请输入成绩:70
C

switch#

switch和if很相似。这里分为switch单值和表达式

老婆的想法:

package main
import "fmt"
func main(){
    var yes string
    fmt.Print("是否看到卖西瓜的?")
    fmt.Scan(&yes)
    fmt.Print("老婆的想法:")
    fmt.Println("买10个包子")
    switch yes {
    case "y":
        fmt.Println("买一个西瓜y")
    case "Y":
        fmt.Println("买一个西瓜Y")
    }
}

输入小y:

[root@marksugar /opt/Golang]# go run switch.go 
是否看到卖西瓜的?y
老婆的想法:买10个包子
买一个西瓜y

输入大Y:

[root@marksugar /opt/Golang]# go run switch.go 
是否看到卖西瓜的?Y
老婆的想法:买10个包子
买一个西瓜Y

输入n:

[root@marksugar /opt/Golang]# go run switch.go 
是否看到卖西瓜的?n
老婆的想法:买10个包子

!!! note

这里的switch可以写成一条
case "y","Y":
    fmt.Println("买一个西瓜")
}

老公的想法

switch default#

package main
import "fmt"
func main(){
    var yes string
    fmt.Print("是否看到卖西瓜的?")
    fmt.Scan(&yes)
    fmt.Print("老公的想法:")
    fmt.Println("买10个包子")
    switch yes {
    case "y","Y":
        fmt.Println("买一个包子")
    default:
        fmt.Println("买十个包子")
    }
}

看到卖西瓜的:

[root@marksugar /opt/Golang]# go run switch.go 
是否看到卖西瓜的?y
老公的想法:买10个包子
买一个包子

没看到买西瓜的:

[root@marksugar /opt/Golang]# go run switch.go 
是否看到卖西瓜的?n
老公的想法:买10个包子
买十个包子

在用switch的方式修改,如果输入大于等于90就打印A,大于等于80打印B,大于等于70打印C,大于等于60打印D,小于60就打印D-不及格。如下:

    var score int
    fmt.Print("请输入成绩:")
    fmt.Scan(&score)

    switch {
    case score >= 90:
        fmt.Println("A")
    case score >= 80:
        fmt.Println("B")
    case score >= 70:
        fmt.Println("C")
    case score >= 60:
        fmt.Println("D")
    default:
        fmt.Println("D-,不及格")
    }

运行

[root@marksugar /opt/Golang]# go run switch.go 
请输入成绩:90
A
[root@marksugar /opt/Golang]# go run switch.go 
请输入成绩:80
B
[root@marksugar /opt/Golang]# go run switch.go
请输入成绩:70
C
[root@marksugar /opt/Golang]# go run switch.go
请输入成绩:60
D
[root@marksugar /opt/Golang]# go run switch.go
请输入成绩:50
D-,不及格

for循环#

重复做一件事情。一般而言,我们会设置一个索引,记录已经加到了多少,并记录结果。那么,至少定义两个变量。

先看下不用for循环的方式。

result := 0

此时定义一个result 0,如果要加到100次,我们需要相加100次

result += 1
result += 2
...
result += 100

如果现在使用for循环,for循环有三个子语句分别是初始化子语句,条件子语句,后值子语句。

for i := 1; i <= 100; i++ {}

如上。

初始化一个值

当满足某个条件时候执行循环

函数体执行完成后执行的代码。

整体的意思就是,i等于1,且i小于等于100,就开始执行i++语句快(反义则是i大于100就不执行)。如下:

package main
import "fmt"
func main(){
    result := 0
    for i:=1;i<=100;i++{
        result += i
        fmt.Println(i)
    }
    fmt.Println(result)
}

运行

[root@marksugar /opt/Golang]# go run for.go 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
5050

这里打印了i,i的确加了100次,结果是5050

!!! note

在go中只有for循环,没有其他的循环,如while等

for一个子语句#

除了上述这种,还有其他的方式实现。比如一个子语句:

result = 0
i := 1
for i<= 100{
    result += i
    i++
}
package main
import "fmt"
func main(){
    result := 0
    i := 1
    for i<= 100{
        result += i
        i++
    }
    fmt.Println(result)
}

运行

[root@marksugar /opt/Golang]# go run for2.go 
5050

for死循环#

在go中,死循环使用for即可

package main
import "fmt"
func main(){
    i :=0
    for {
        fmt.Println(i)
        i++
    }
}

除此之外,for循环还有遍历的for range

for range#

for range在go中非常常用,可以遍历字符串,数组,切片,映射,管道。

一般而言,for range遍历,有一个索引和一个值,这与需要变量的对象有关。 简单的认为一个是索引index,和一个value即可

desc := "我是marksugar"
for index,value := range desc {
    fmt.Printf("%d %T %q\n",index,value,value)
}

运行

[root@marksugar /opt/Golang]# go run for3.go 
0 int32 '我'
3 int32 '是'
6 int32 'm'
7 int32 'a'
8 int32 'r'
9 int32 'k'
10 int32 's'
11 int32 'u'
12 int32 'g'
13 int32 'a'
14 int32 'r'
  • 在for range中,如果不需要index或者value,可以使用_(下划线)不接收

desc := "我是marksugar" for _,value := range desc {} 注意:这里的空白标识符是go内置,我们只能对它进行赋值

比如下面这段代码:

var value int _,value = 1,2 fmt.Println(value) 这里的输出是2。这里值得注意的是,因为空白标识符是内置的,不能使用:=(冒号)定义 。如果一定要使用:=赋值,在简短声明中,至少需要有一个是新定义的。那么需要如下定义:

package main import "fmt" func main(){ var value int _,value = 1,4 fmt.Println(value) } 运行:

[root@linuxea-marksugar /opt/Golang/work2]# go run biaoshifu.go 4 如果这里使用简短声明就会报错的

# command-line-arguments ./biaoshifu.go:5:10: no new variables on left side of := ./biaoshifu.go:7:1: syntax error: unexpected EOF, expecting } 如果我们要使用简短声明就需要一个新的变量,如下

package main import "fmt" func main(){ var value int _,value,newvalue := 1,4,5 fmt.Println(value,newvalue) } 运行

[root@linuxea-marksugar /opt/Golang/work2]# go run biaoshifu.go 4 5

brack和continue#

brack和continue 只能在循环中使用

我们先定义,i:=0,并且i<5,正常情况下,将会打印0~4

package main
import "fmt"
func main(){
    for i :=0;i<5;i++{
        fmt.Println(i)
    }
}

运行

[root@marksugar /opt/Golang]# go run brack1.go 
0
1
2
3
4

为了能够加以区分,我们在这段代码上分别加上break和continue

如果i等于3就执行continue,break

[root@marksugar /opt/Golang]# cat brack.go 
package main
import "fmt"
func main(){
    fmt.Println("continue:")
    for i :=0;i<5;i++{
        if i == 3 {
            continue
        }
        fmt.Println(i)
    }
    fmt.Println("break:")

    for i :=0;i<5; i++{
        if i ==3 {
            break
        }
        fmt.Println(i)
    }
}

运行:

[root@marksugar /opt/Golang]# go run brack.go 
continue:
0
1
2
4
break:
0
1
2

如上所示:

在continue中,当i等于3就跳过继续执行子语句之后的条件,直到满足条件小于5

在break中,当i等于3就停止执行后面的子语句。

continue执行到就会跳过本次执行,继续循环

break执行到后就会跳出循环

13.goto#

与brack和continue不同,goto只有在C和go中才有。

goto作为跳转,需要定义一个label标签。这个标签决定跳转到哪里。并且break也可以配合标签使用,见示例3

goto示例1#

但输入内容为c/u/r/d,打印create,update,read,delete,如果输入都不是,就重新执行循环。也就是说只有输入c/u/r/d程序才会结束。

代码如下:

package main
import "fmt"
func main(){

START:
    fmt.Print("input:(c/u/r/d):")
    var in string
    fmt.Scan(&in)

    for {
    if in == "c"{
        fmt.Println("create")
        break
    }else if in == "u" {
        fmt.Println("update")
        break
    }else if in == "r" {
        fmt.Println("read")
        break
    }else if in == "d" {
        fmt.Println("delete")
        break
    }else if in != "c" &&  in != "u" && in != "r" && in != "d" {
        goto START
    }
    }
}

跳出在 这里使用不等于!=,如果输入的不等于就跳转到标签START。如果输入c/u/r/d任意一个即可。

运行:

[root@marksugar /opt/Golang]# go run goto.go 
input:(c/u/r/d):s
input:(c/u/r/d):.
input:(c/u/r/d):1
input:(c/u/r/d):2
input:(c/u/r/d):3
input:(c/u/r/d):a
input:(c/u/r/d):c
create

goto示例2#

从1加到100的和,不用for循环

如果i小于100,就result就等于i,进行i++,跳转到START判断继续循环。直到大于100,就跳转到FOREND

代码如下:

package main
import "fmt"
func main(){

    result := 0
    i := 1

START:
    for i>100 {
        fmt.Println(i)
        goto FOREND
    }
    result += i
    i++
    goto START
FOREND:
        fmt.Println(result)
}

运行

[root@marksugar /opt/Golang]# go run goto2.go
101
5050

goto示例3#

定义嵌套循环,分别i和j,i和j相乘,如果等于9就结束程序。使用break 和BREAKEND标签。代码如下:

package main
import "fmt"
func main(){
BREAKEND:
    for i :=0;i<5;i++{
        for j :=0; j<5;j++{
            if i*j == 9 {
                break BREAKEND
            }
            fmt.Println(i,j,i*j)
        }
    }
}

!!! note break的标签需要在循环层级之上,不能写在下面

运行:

[root@marksugar /opt/Golang]# go run brack2.go 
0 0 0
0 1 0
0 2 0
0 3 0
0 4 0
1 0 0
1 1 1
1 2 2
1 3 3
1 4 4
2 0 0
2 1 2
2 2 4
2 3 6
2 4 8
3 0 0
3 1 3
3 2 6

练习题#

  1. 打印乘法口诀 for + if + fmt.Println + fmt.Printf

  2. 猜数字游戏 for if continue/break a. 生成一个[0, 100)随机数 b. 让用户最多猜 5次(从命令行输入一个整数) 猜的太大 => 提示太大了,你还有N此猜测机会 猜的太小 => 提示太小了,你还有N此猜测机会 猜中了 => 猜中了

5次都没猜中 => 退出,并提示太笨了

挑战: 当5此都没有猜中:提示太笨了,重新开始猜数游戏(重新生成随机数,重新开始5次计数)

练习题1示例#

成法表,从1开始相乘,1*1,1*2,1*3,等等,这样使用for循环可以实现,如下:

for i :=1;i<=line;i++ {
    fmt.Printf("%d * %d = %-2d   ",i,line,i*line)
}
1x1
1x2 2x2
1x3 2x3 3x3
1x4 2x4 3x4 4x4

这里而后还需要进行一次循环,9以内要进行相乘。最终如下:

package main
import "fmt"

func main(){
    for line :=1;line <=9;line++ {
        for i :=1;i<=line;i++ {
            fmt.Print(i,"x",line,"=",i*line,"\t")
        }
    fmt.Println()
    }
}

运行

[root@linuxea-marksugar /opt/Golang]# go run  99xfb2.go 
1x1=1   
1x2=2   2x2=4   
1x3=3   2x3=6   3x3=9   
1x4=4   2x4=8   3x4=12  4x4=16  
1x5=5   2x5=10  3x5=15  4x5=20  5x5=25  
1x6=6   2x6=12  3x6=18  4x6=24  5x6=30  6x6=36  
1x7=7   2x7=14  3x7=21  4x7=28  5x7=35  6x7=42  7x7=49  
1x8=8   2x8=16  3x8=24  4x8=32  5x8=40  6x8=48  7x8=56  8x8=64  
1x9=9   2x9=18  3x9=27  4x9=36  5x9=45  6x9=54  7x9=63  8x9=72  9x9=81  

或者这样,使用Printf,这里还是用了负号,左对齐-2d

package main
import "fmt"

func main(){
    for line :=1;line <=9;line++ {
        for i :=1;i<=line;i++ {
            fmt.Printf("%d * %d = %-2d   ",i,line,i*line)
        }
    fmt.Println()
    }
}

运行:

[root@marksugar /opt/Golang]# go run 99xfb.go 
1 * 1 = 1    
1 * 2 = 2    2 * 2 = 4    
1 * 3 = 3    2 * 3 = 6    3 * 3 = 9    
1 * 4 = 4    2 * 4 = 8    3 * 4 = 12   4 * 4 = 16   
1 * 5 = 5    2 * 5 = 10   3 * 5 = 15   4 * 5 = 20   5 * 5 = 25   
1 * 6 = 6    2 * 6 = 12   3 * 6 = 18   4 * 6 = 24   5 * 6 = 30   6 * 6 = 36   
1 * 7 = 7    2 * 7 = 14   3 * 7 = 21   4 * 7 = 28   5 * 7 = 35   6 * 7 = 42   7 * 7 = 49   
1 * 8 = 8    2 * 8 = 16   3 * 8 = 24   4 * 8 = 32   5 * 8 = 40   6 * 8 = 48   7 * 8 = 56   8 * 8 = 64   
1 * 9 = 9    2 * 9 = 18   3 * 9 = 27   4 * 9 = 36   5 * 9 = 45   6 * 9 = 54   7 * 9 = 63   8 * 9 = 72   9 * 9 = 81   

2.猜数字游戏 for if continue/break a. 生成一个[0, 100)随机数 b. 让用户最多猜 5次(从命令行输入一个整数) 猜的太大 => 提示太大了,你还有N此猜测机会 猜的太小 => 提示太小了,你还有N此猜测机会 猜中了 => 猜中了

5次都没猜中 => 退出,并提示太笨了

挑战: 当5此都没有猜中:提示太笨了,重新开始猜数游戏(重新生成随机数,重新开始5次计数)

!!! note 需要一个随机数的种子

会用到time和math/rand模块

package main

import (
    "fmt"
    "math/rand"
    "time"
)
func main(){
    rand.Seed(time.Now().Unix())
    fmt.Println(rand.Int())
}

这样我们会拿到一串随机数

[root@marksugar /opt/Golang]# go run work11.go 
4539660804304182971
[root@marksugar /opt/Golang]# go run work11.go 
125010350273079313
[root@marksugar /opt/Golang]# go run work11.go 
5357909466568961262

而后使用% 100对0~100取余

package main

import (
    "fmt"
    "math/rand"
    "time"
)
func main(){
    rand.Seed(time.Now().Unix())
    fmt.Println(rand.Int() % 100)
}

运行

[root@marksugar /opt/Golang]# go run work11.go 
90
[root@marksugar /opt/Golang]# go run work11.go 
15
[root@marksugar /opt/Golang]# go run work11.go 
15
[root@marksugar /opt/Golang]# go run work11.go 
89

!!! note 也可以使用Intn(100)也可以取余

    rand.Seed(time.Now().Unix())
    fmt.Println(rand.Intn(100))
[root@marksugar /opt/Golang]# go run work11.go 
72
[root@marksugar /opt/Golang]# go run work11.go 
2
[root@marksugar /opt/Golang]# go run work11.go 
15

练习题2示例#

代码如下:

package main

import (
    "fmt"
    "math/rand"
    "strconv"
    "time"
)
func dadata(sjs int) int{
    rand.Seed(time.Now().UnixNano())   // 系统时间为随机种子
    return rand.Intn(sjs)
}
func main(){
    for {
    sjs := dadata(100)
    fmt.Println(sjs)
    num := 3
    var dA1 string

    for i:=0;i<=3;i++{
        rnum := num - i
        fmt.Print("开始猜数字游戏,请输入:")
        fmt.Scanf("%v",&dA1)
        dA1,err := strconv.ParseInt(dA1,10,0)  // 判断输入的是整数
        if err != nil {
            fmt.Println("你输入的不是数字",err)
            break
        }else if int(dA1) == sjs {
            fmt.Printf("恭喜你猜对了数字是%v!", sjs)
            goto ENDD
        } else if int(dA1) > sjs {
            fmt.Printf("猜大了,你还可以猜测%v次\n",rnum)
        } else if int(dA1) < sjs {
            fmt.Printf("猜小了,你还可以猜测%v次\n",rnum)
        }
    }
    }
ENDD:
}

运行

[root@marksugar /opt/Golang]# go run work1.go 
5
开始猜数字游戏,请输入:6
猜大了,你还可以猜测3次
开始猜数字游戏,请输入:9
猜大了,你还可以猜测2次
开始猜数字游戏,请输入:8
猜大了,你还可以猜测1次
开始猜数字游戏,请输入:2
猜小了,你还可以猜测0次
39
开始猜数字游戏,请输入:39
恭喜你猜对了数字是39!

当然,这里也可以使用bool类型来判断

package main

import (
    "fmt"
    "math/rand"
    "strconv"
    "time"
)
func dadata(sjs int) int{
    rand.Seed(time.Now().UnixNano())   // 系统时间为随机种子
    return rand.Intn(sjs)
}
func main(){
    for {
        sjs := dadata(100)
        fmt.Println(sjs)
        num := 3
        var okk bool
        var dA1 string

        for i:=0;i<=3;i++{
            rnum := num - i
            fmt.Print("开始猜数字游戏,请输入:")
            fmt.Scanf("%v",&dA1)
            dA1,err := strconv.ParseInt(dA1,10,0)  // 判断输入的是整数
            if err != nil {
                fmt.Println("你输入的不是数字",err)
                break
            }else if int(dA1) == sjs {
                okk = true
                fmt.Printf("恭喜你猜对了数字是%v!", sjs)
                goto ENDD
            } else if int(dA1) > sjs {
                fmt.Printf("猜大了,你还可以猜测%v次\n",rnum)
            } else {
                fmt.Printf("猜小了,你还可以猜测%v次\n",rnum)
            }
        }
        if !okk {
            fmt.Println("游戏结束!")
            }
    }
ENDD:
}

运行

[root@linuxea-marksugar /opt/Golang]# go run work3.go
69
开始猜数字游戏,请输入:321
猜大了,你还可以猜测3次
开始猜数字游戏,请输入:321
猜大了,你还可以猜测2次
开始猜数字游戏,请输入:321
猜大了,你还可以猜测1次
开始猜数字游戏,请输入:312
猜大了,你还可以猜测0次
游戏结束!
5
开始猜数字游戏,请输入:321
猜大了,你还可以猜测3次
开始猜数字游戏,请输入:312
猜大了,你还可以猜测2次
开始猜数字游戏,请输入:321
猜大了,你还可以猜测1次
开始猜数字游戏,请输入:312
猜大了,你还可以猜测0次
游戏结束!
62
开始猜数字游戏,请输入:62
恭喜你猜对了数字是62!