Golang流程控制语句

Go 条件语句

img

语句描述
if 语句if 语句 由一个布尔表达式后紧跟一个或多个语句组成。
if…else 语句if 语句 后可以使用可选的 else 语句, else 语句中的表达式在布尔表达式为 false 时执行。
if 嵌套语句你可以在 if 或 else if 语句中嵌入一个或多个 if 或 else 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")
    }
}
2、case 条件语句为 true
3、case 条件语句为 false
4、case 条件语句为 true

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

select 语句

select 是 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
31
32
33
34
35
36
37
package main

import (
"fmt"
"time"
)

func main() {
// 创建两个无缓冲的 channel,用于在 goroutine 之间传递字符串消息
c1 := make(chan string)
c2 := make(chan string)

// 启动第一个 goroutine
go func() {
// 暂停 1 秒钟后向 c1 发送消息 "one"
time.Sleep(1 * time.Second)
c1 <- "one"
}()

// 启动第二个 goroutine
go func() {
// 暂停 2 秒钟后向 c2 发送消息 "two"
time.Sleep(2 * time.Second)
c2 <- "two"
}()

// 使用 select 语句等待并接收来自 c1 或 c2 的消息
// select 语句用于监听多个通道,并且当任意一个通道有数据可读时立即执行相应的 case。
for i := 0; i < 2; i++ {
select {
case msg1 := <-c1:
fmt.Println("received", msg1)
case msg2 := <-c2:
fmt.Println("received", msg2)
}
}
}
  • Goroutine:Go 中的轻量级线程,允许并发执行任务。
  • Channel:用于在不同 goroutine 之间传递数据的安全管道。
  • Select:用于监听多个通道并在其中一个通道准备好时执行相应操作。

执行流程

  1. 程序启动后,首先创建了两个通道 c1 和 c2。
  2. 启动了两个 goroutine,它们分别会在 1 秒和 2 秒后向各自的通道发送消息。
  3. 主函数中的 for 循环会运行两次,每次都会进入 select 语句等待消息。
  4. 由于第一个 goroutine 只需要 1 秒钟就会发送消息到 c1,所以在第一次循环中,select 语句会接收到 c1 的消息 "one" 并打印出来。
  5. 第二次循环时,第二个 goroutine 已经完成了它的 2 秒钟延迟,并将消息 "two" 发送到 c2,因此这次 select 语句会接收到 c2 的消息并打印出来。

以上代码执行结果为:

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

import "fmt"

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

// 启动第一个 goroutine,无限循环向 ch1 发送消息
go func() {
for {
ch1 <- "from 1"
}
}()

// 启动第二个 goroutine,无限循环向 ch2 发送消息
go func() {
for {
ch2 <- "from 2"
}
}()

// 主 goroutine 无限循环,使用 select 监听 ch1 和 ch2 的消息
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")
    }
    }
    }