Golang流程控制语句

Go 条件语句

img

语句描述
if 语句if 语句 由一个布尔表达式后紧跟一个或多个语句组成。
if…else 语句if 语句 后可以使用可选的 else 语句, else 语句中的表达式在布尔表达式为 false 时执行。
if 嵌套语句你可以在 ifelse if 语句中嵌入一个或多个 ifelse if 语句。
switch 语句switch 语句用于基于不同条件执行不同动作。
select 语句select 语句类似于 switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。

if语句

语法
1
2
3
if 条件 {
成立后,此代码块执行
}
1
2
3
4
5
if 条件 {
成立后,此代码块执行
}else{
不成立,此代码块执行
}

示例:

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
package main

func main() {
/*
if true {
fmt.Println("666")
}else{
fmt.Println("999")
}
*/

/*
if 1 > 2 {
fmt.Println("666")
} else {
fmt.Println("999")
}
*/

/*
flag := false
if flag {
fmt.Println("条件成立")
}else{
fmt.Println("条件不成立")
}
*/

// 练习题1:用户输入姓名,判断是否正确
/*
var name string
fmt.Print("请输入姓名:")
fmt.Scanln(&name)
if name == "gooo" {
fmt.Println("用户名输入正确")
} else {
fmt.Println("用户名输入错误")
}
*/
// 练习题2:用户输入数字,判断奇数、偶数
/*
var number int
fmt.Print("请输入数字:")
fmt.Scanln(&number)
if number % 2 == 0{
fmt.Println("您输入的是偶数")
}else{
fmt.Println("您输入的是奇数")
}
*/
// 练习题3:用户和密码,判断用户名密码是否正确。
/*


var username, password string
fmt.Print("请输入用户名:")
fmt.Scanln(&username)

fmt.Print("请输入密码:")
fmt.Scanln(&password)

if username == "gooo" && password == "sb" {
fmt.Println("欢迎登录pornhub")
} else {
fmt.Println("用户名或密码错误")
}
*/
// 练习题4:请输入用户名校验是否是VIP
/*
var username string
fmt.Print("请输入用户名:")
fmt.Scanln(&username)

if username == "gooo" || username == "eric" {
fmt.Println("天上人间大VIP")
} else {
fmt.Println("屌丝")
}
*/
}

多条件判断
1
2
3
4
5
6
7
8
9
if 条件A{
...
}else if 条件B{
...
}else if 条件C{
...
}else{
...
}

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main

import "fmt"

func main() {
var length int
fmt.Print("请输入你的长度:")
fmt.Scanln(&length)

if length < 1 {
fmt.Println("没用的东西,还特么是坑")
} else if length < 6 {
fmt.Println("刚刚能用")
} else if length < 18 {
fmt.Println("生活和谐")
} else {
fmt.Println("太特么大了")
}
}
嵌套
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
package main

import "fmt"

func main() {
fmt.Println("欢迎致电10086,1.话费相关;2.业务办理;3.人工服务。")

var number int
fmt.Scanln(&number)

if number == 1 {
fmt.Println("话费服务,1.交话费;2.查询。")
var n1 int
fmt.Scanln(&n1)
if n1 == 1 {
fmt.Println("缴话费啦")
} else if n1 == 2 {
fmt.Println("查话费了")
} else {
fmt.Println("输入错误")
}
} else if number == 2 {
fmt.Println("业务办理")
} else if number == 3 {
fmt.Println("人工服务")
} else {
fmt.Println("输入错误")
}

// 建议:条件的嵌套不要太多
}

switch 语句

switch 语句用于基于不同条件执行不同动作,每一个 case 分支都是唯一的,从上至下逐一测试,直到匹配为止。

switch 语句执行的过程从上至下,直到找到匹配项,匹配项后面也不需要再加 break。

switch 默认情况下 case 最后自带 break 语句,匹配成功后就不会执行其他 case,如果我们需要执行后面的 case,可以使用 fallthrough

语法

Go 编程语言中 switch 语句的语法如下:

1
2
3
4
5
6
7
8
switch var1 {
case val1:
...
case val2:
...
default:
...
}

变量 var1 可以是任何类型,而 val1 和 val2 则可以是同类型的任意值。类型不被局限于常量或整数,但必须是相同的类型;或者最终结果为相同类型的表达式。

您可以同时测试多个可能符合条件的值,使用逗号分割它们,例如:case val1, val2, val3。

流程图:

img

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
package main

import "fmt"

func main() {
   /* 定义局部变量 */
   var grade string = "B"
   var marks int = 90

   switch marks {
      case 90: grade = "A"
      case 80: grade = "B"
      case 50,60,70 : grade = "C"
      default: grade = "D"  
   }

   switch {
      case grade == "A" :
         fmt.Printf("优秀!\n" )    
      case grade == "B", grade == "C" :
         fmt.Printf("良好\n" )      
      case grade == "D" :
         fmt.Printf("及格\n" )      
      case grade == "F":
         fmt.Printf("不及格\n" )
      default:
         fmt.Printf("差\n" );
   }
   fmt.Printf("你的等级是 %s\n", grade );      
}

以上代码执行结果为:

1
2
优秀!
你的等级是 A
Type Switch

switch 语句还可以被用于 type-switch 来判断某个 interface 变量中实际存储的变量类型。

Type Switch 语法格式如下:

1
2
3
4
5
6
7
8
9
switch x.(type){
case type:
statement(s);
case type:
statement(s);
/* 你可以定义任意个数的case */
default: /* 可选 */
statement(s);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main

import "fmt"

func main() {
   var x interface{}
     
   switch i := x.(type) {
      case nil:  
         fmt.Printf(" x 的类型 :%T",i)                
      case int:  
         fmt.Printf("x 是 int 型")                      
      case float64:
         fmt.Printf("x 是 float64 型")          
      case func(int) float64:
         fmt.Printf("x 是 func(int) 型")                      
      case bool, string:
         fmt.Printf("x 是 bool 或 string 型" )      
      default:
         fmt.Printf("未知型")    
   }  
}

x 的类型 :<nil>
fallthrough

使用 fallthrough 会强制执行后面的 case 语句,fallthrough 不会判断下一条 case 的表达式结果是否为 true。

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
package main

import "fmt"

func main() {

    switch {
    case false:
            fmt.Println("1、case 条件语句为 false")
            fallthrough
    case true:
            fmt.Println("2、case 条件语句为 true")
            fallthrough
    case false:
            fmt.Println("3、case 条件语句为 false")
            fallthrough
    case true:
            fmt.Println("4、case 条件语句为 true")
    case false:
            fmt.Println("5、case 条件语句为 false")
            fallthrough
    default:
            fmt.Println("6、默认 case")
    }
}
2case 条件语句为 true
3case 条件语句为 false
4case 条件语句为 true

从以上代码输出的结果可以看出:switch 从第一个判断表达式为 true 的 case 开始执行,如果 case 带有 fallthrough,程序会继续执行下一条 case,且它不会去判断下一个 case 的表达式是否为 true。

select 语句

elect 是 Go 中的一个控制结构,类似于 switch 语句。

select 语句只能用于通道操作,每个 case 必须是一个通道操作,要么是发送要么是接收。

select 语句会监听所有指定的通道上的操作,一旦其中一个通道准备好就会执行相应的代码块。

如果多个通道都准备好,那么 select 语句会随机选择一个通道执行。如果所有通道都没有准备好,那么执行 default 块中的代码。

语法

Go 编程语言中 select 语句的语法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
select {
  case <- channel1:
    // 执行的代码
  case value := <- channel2:
    // 执行的代码
  case channel3 <- value:
    // 执行的代码

    // 你可以定义任意数量的 case

  default:
    // 所有通道都没有准备好,执行的代码
}

以下描述了 select 语句的语法:

  • 每个 case 都必须是一个通道

  • 所有 channel 表达式都会被求值

  • 所有被发送的表达式都会被求值

  • 如果任意某个通道可以进行,它就执行,其他被忽略。

  • 如果有多个 case 都可以运行,select 会随机公平地选出一个执行,其他不会执行。

    否则:

    1. 如果有 default 子句,则执行该语句。
    2. 如果没有 default 子句,select 将阻塞,直到某个通道可以运行;Go 不会重新对 channel 或值进行求值。
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
package main

import (
    "fmt"
    "time"
)

func main() {

    c1 := make(chan string)
    c2 := make(chan string)

    go func() {
        time.Sleep(1 * time.Second)
        c1 <- "one"
    }()
    go func() {
        time.Sleep(2 * time.Second)
        c2 <- "two"
    }()

    for i := 0; i < 2; i++ {
        select {
        case msg1 := <-c1:
            fmt.Println("received", msg1)
        case msg2 := <-c2:
            fmt.Println("received", msg2)
        }
    }
}

以上代码执行结果为:

1
2
received one
received two

以上实例中,我们创建了两个通道 c1 和 c2。

select 语句等待两个通道的数据。如果接收到 c1 的数据,就会打印 “received one”;如果接收到 c2 的数据,就会打印 “received two”。

以下实例中,我们定义了两个通道,并启动了两个协程(Goroutine)从这两个通道中获取数据。在 main 函数中,我们使用 select 语句在这两个通道中进行非阻塞的选择,如果两个通道都没有可用的数据,就执行 default 子句中的语句。

以下实例执行后会不断地从两个通道中获取到的数据,当两个通道都没有可用的数据时,会输出 “no message received”。

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
package main

import "fmt"

func main() {
// 定义两个通道
ch1 := make(chan string)
ch2 := make(chan string)

// 启动两个 goroutine,分别从两个通道中获取数据
go func() {
for {
ch1 <- "from 1"
}
}()
go func() {
for {
ch2 <- "from 2"
}
}()

// 使用 select 语句非阻塞地从两个通道中获取数据
for {
select {
case msg1 := <-ch1:
fmt.Println(msg1)
case msg2 := <-ch2:
fmt.Println(msg2)
default:
// 如果两个通道都没有可用的数据,则执行这里的语句
fmt.Println("no message received")
}
}
}

Go 循环语句

在不少实际问题中有许多具有规律性的重复操作,因此在程序中就需要重复执行某些语句。一组被重复执行的语句称之为循环体,能否继续重复,决定循环的终止条件。

与其它主流编程语言不同的的是,Go语言中的循环语句只支持 for 关键字,而不支持 while 和 do-while 结构。

img

for 循环

语法

Go 语言的 For 循环有 3 种形式,只有其中的一种使用分号。

和 C 语言的 for 一样:

1
for init; condition; post { }

和 C 的 while 一样:

1
for condition { }

和 C 的 for(;;) 一样:

1
for { }
  • init: 一般为赋值表达式,给控制变量赋初值;
  • condition: 关系表达式或逻辑表达式,循环控制条件;
  • post: 一般为赋值表达式,给控制变量增量或减量。

for语句执行过程如下:

  • 1、先对表达式 1 赋初值;
  • 2、判别赋值表达式 init 是否满足给定条件,若其值为真,满足循环条件,则执行循环体内语句,然后执行 post,进入第二次循环,再判别 condition;否则判断 condition 的值为假,不满足条件,就终止for循环,执行循环体外语句。

for 循环的 range 格式可以对 slice、map、数组、字符串等进行迭代循环。格式如下:

1
2
3
for key, value := range oldMap {
newMap[key] = value
}

以上代码中的 key 和 value 是可以省略。

如果只想读取 key,格式如下:

1
for key := range oldMap

或者这样:

for key, _ := range oldMap

如果只想读取 value,格式如下:

1
for _, value := range oldMap

for 语句语法流程如下图所示:

img

简单for循环

通过关系表达式或逻辑表达式控制循环

1
for  condition { }

简单循环案例:

1
2
3
4
5
6
7
count := 0       // 初始化语句
for count < 10 { // 条件判断
fmt.Println(count)
fmt.Println("小于10,+1")
count++ // 步进语句
}
fmt.Println("已经大于10了,end")
1
2
3
4
5
6
7
count := 10     // 初始化语句
for count > 0 { // 条件判断
fmt.Println(count)
fmt.Println("大于0,-1")
count-- // 步-语句
}
fmt.Println("已经小于等于0了,end")
三要素for循环(核心)

将初始化语句、条件判断以及步进语句格式固定化的循环方式,本质上和上面的for循环没有区别。

1
2
3
for init;condition;post { 
// 循环体语句
}
  • init: 初始化语句,一般为赋值表达式,给控制变量赋初值;
  • condition:条件判断,一般是关系表达式或逻辑表达式,循环控制条件;
  • post: 步进语句,一般为赋值表达式,给控制变量增量或减量。
1
2
3
for i := 1; i < 10; i++ {
fmt.Println(i)
}

执行流程(关键):

(1)初始语句

(2)条件判断,布尔值为真则执行一次循环体,为假则退出循环

(3)执行一次循环体语句结束后,再执行步进语句,然后回到步骤(2),依次循环

案例1:计算1-100的和

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*  var s = 0
s += 1
s += 2
s += 3
s += 4
s += 5
s += 6
s += 7
s += 8
s += 9
s += 10
fmt.Println(s)*/

// 如果是1+2+3+....100呢?如何借助循环语法实现
var s = 0
for i := 1; i <= 100; i++ {
s += i
}
fmt.Println(s)

分支与循环的嵌套使用

循环与和分支语句是可以相互嵌套使用的,即分支语句中使用循环语句,循环语句中使用分支语句。

打印1-100中所有的偶数

1
2
3
4
5
for i := 1; i <= 100; i++ {
if i%2 == 0 {
fmt.Println(i)
}
}

无限循环案例

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
/*
无限循环
for true{}
*/

// 循环中嵌入分支语句
func main() {
fmt.Printf(`
1、普通攻击
2、超级攻击
3、使用道具
4、逃跑
`)
for true {
var choice int
fmt.Printf("请输入选择:")
fmt.Scanln(&choice)
//fmt.Println(choice,reflect.TypeOf(choice))

switch choice {
case 1:
fmt.Println("普通攻击")
case 2:
fmt.Println("超级攻击")
case 3:
fmt.Println("使用道具")
case 4:
fmt.Println("逃跑")
default:
fmt.Println("输入有误!")
}
}
}

输入正整数num,大于100,则打印1-num,小于100,则打印num-1?

1
2
3
4
5
6
7
8
9
10
11
12
var num int
fmt.Scanln(&num)

if num > 100 {
for i := 1; i <= num; i++ {
fmt.Println(i)
}
} else {
for i := num; i > 0; i-- {
fmt.Println(i)
}
}

退出循环

果想提前结束循环(在不满足结束条件的情况下结束循环),可以使用break或continue关键字。

  • break 用来跳出整个循环语句,也就是跳出所有的循环次数;
  • continue 用来跳出当次循环,也就是跳过当前的一次循环。
break语句

当 break 关键字用于 for 循环时,会终止循环而执行整个循环语句后面的代码。break 关键字通常和 if 语句一起使用,即满足某个条件时便跳出循环,继续执行循环语句下面的代码。

1
2
3
4
5
6
7
for i := 0; i < 10; i++ {
if i == 8 {
break
}
fmt.Println(":", i)
}
fmt.Println("end")

break

continue语句

break 语句使得循环语句还没有完全执行完就提前结束,与之相反,continue 语句并不终止当前的循环语句的执行,仅仅是终止当前循环变量 i 所控制的这一次循环,而继续执行该循环语句。continue 语句的实际含义是“忽略 continue 之后的所有循环体语句,回到循环的顶部并开始下一次循环”

1
2
3
4
5
6
7
for i := 0; i < 10; i++ {
if i == 8 {
continue
}
fmt.Println(":", i)
}
fmt.Println("end")

continue

案例: 计算 1 - 2 + 3 - 4 + … + 99 中除了88以外所有数的总和?

循环嵌套

在一个循环体语句中又包含另一个循环语句,称为循环嵌套

独立嵌套

在控制台上打印一个五行五列的矩形,如下图所示

1
2
3
4
5
6
7
for i := 0; i < 5; i++ {

for j := 0; j < 5; j++ {
fmt.Print("*")
}
fmt.Print("\n")
}
1
2
3
4
5
*****
*****
*****
*****
*****

123

关联嵌套

在控制台上打印一个如下图所示的三角形

1
2
3
4
5
*
**
***
****
*****
1
2
3
4
5
6
for i := 0; i < 5; i++ {
for j := 0; j <= i; j++ {
fmt.Printf("*")
}
fmt.Println()
}

Go 阶段练习题

  1. 提⽰⽤户输入⿇花藤. 判断⽤户输入的对不对。如果对, 提⽰真聪明, 如果不对, 提⽰你 是傻逼么。

  2. 提示用户输入两个数字,计算两个数的和并输出。

  3. 提示用户输入姓名、位置、行为三个值,然后做字符串的拼接 并输出,例如:xx 在 xx 做 xx 。

  4. 设定一个理想数字比如:66,让用户输入数字,如果比66大,则显示猜测的结果大了;如果比66小,则显示猜测的结果小了;只有等于66,显示猜测结果正确。

  5. 写程序,输出成绩等级。成绩有ABCDE5个等级,与分数的对应关系如下.

    1
    2
    3
    4
    5
    A    90-100
    B 80-89
    C 60-79
    D 40-59
    E 0-39

    要求用户输入0-100的数字后,正确输出他的对应成绩等级。

    答案:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    package main

    import "fmt"

    func main() {
    var name string
    fmt.Println("请输入⿇花藤")
    fmt.Scanln(&name)
    if name == "⿇花藤" {
    fmt.Println("真聪明")
    } else {
    fmt.Println("是傻逼么")
    }
    }
    1
    2
    3
    4
    var x, y int
    fmt.Println("请输入两个数字")
    fmt.Scanln(&x, &y)
    fmt.Printf("%d + %d = %d", x, y, x+y)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    func main() {
    var name, weizhi, xingwei string
    fmt.Println("你叫什么")
    fmt.Scanln(&name)
    fmt.Println("在做什么")
    fmt.Scanln(&xingwei)
    fmt.Println("在什么位置")
    fmt.Scanln(&weizhi)
    fmt.Printf("%s在%s做%s", name, weizhi, xingwei)
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    func main() {

    for {
    var num int
    fmt.Println("猜数字游戏,请输入你猜想的数字: ")
    fmt.Scanln(&num)
    if num > 66 {
    fmt.Println("大了")
    } else if num == 66 {
    fmt.Println("恭喜你猜对了")
    break
    } else {
    fmt.Println("小了")
    }
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    func main() {

    for {
    var num int
    fmt.Println("请输入你的成绩: ")
    fmt.Scanln(&num)
    if num >= 90 && num <= 100 {
    fmt.Println("A")
    } else if num >= 80 && num <= 89 {
    fmt.Println("B")
    } else if num >= 60 && num <= 79 {
    fmt.Println("C")
    } else if num >= 40 && num <= 59 {
    fmt.Println("D")
    } else if num >= 0 && num <= 39 {
    fmt.Println("E")
    }
    }
    }