第十章:Go语言流程控制

golang-gopher.png

1. 概述

程序中的流程控制语句,用于设置程序的执行次序,体现程序执行流程的实现部分,建立程序的基本逻辑结构.

2. 条件判断分支- if

Go语言中使用 if 关键字进行条件判断 ,条件判断的语句终值为 true 或者 false

2.1 单分支

语法格式 :

if 表达式 {

分支1

}

package main

import "fmt"

func main(){
    var condition  bool  = true
    age := 19
    if condition {
        fmt.Println("condition is true ")
    }
    if age >= 18{
        fmt.Println("成年人的世界,没有容易二字")
    }
    // 也可以使用 ! 进行反向判断
    if !(1>2){
        fmt.Println("1不大于2")
    }

}

$ go run main.go
condition is true 
成年人的世界,没有容易二字
1不大于2

if 后面的条件判断语句可以是一个表达式

package main

import "fmt"

func compareNum(x, y int) bool {
    if x < y {
        return false
    }
    return true
}
func main() {
    // if 后面的可以是一个表达式
    if month := 8; month <= 9 {
        fmt.Printf("现在是%d月份\n", month)
    }
    x := 90
    y := 10
    // 也是一个表达式
    if compareNum(x, y) {
        fmt.Printf("x = %d 大于 y = %d\n", x, y)
    }

}

$ go run main.go
现在是8月份
x = 90 大于 y = 10

2.2 双分支

语法格式 :

if 表达式{

​ 分支1

}else{

​ 分支2

}

package main

import "fmt"

func main(){
    var age int
    fmt.Println("请输入年龄[0~120] : ")
    fmt.Scanln(&age)
    if age >18{
        fmt.Println("成年人")
    }else{
        fmt.Println("未成年人")
    }
}

$ go run main.go
请输入年龄[0~120] : 
99
成年人

注意 if后面跟的表达式的形式的最终结果是bool类型,不论表达式以怎么样的形式出现

package main

import "fmt"

func main() {
    var n1 float64 = 89.99
    var n2 float64 = 10.01
    b := true
    if n1 >= 88.00 || n2 < 11.00 && (n1+n2) > 99.99 && b {
        fmt.Println("条件都满足")
    } else {
        fmt.Println("条件都不满足")
    }
}

$ go run main.go
条件都满足

2.3 多分支

多分支控制

if 表达式1 {

​ 分支1

}else if 表达式2{

​ 分支2

}else if 表达式3{

​ 分支3

}...

package main

import "fmt"

func main() {
    var score int
    fmt.Println("请输入学生分数[0~100] : ")
    fmt.Scanln(&score)
    if score > 100 || score < 0 {
        fmt.Println("分数范围不正确")
    } else if score >= 90 {
        fmt.Println("成绩优秀")
    } else if score >= 80 {
        fmt.Println("成绩良好")
    } else if score >= 70{
        fmt.Println("成绩普通")
    } else if score >= 60 {
        fmt.Println("成绩及格")
    }else{
        fmt.Println("成绩不及格")
    }
}

$ go run main.go
请输入学生分数[0~100] : 
76
成绩普通

3. 条件选择分支- switch

switch是根据不同的执行条件,执行不同的逻辑分支代码,每个case分支都是唯一的,自上而下逐一匹配

  • switch 和case 的表达式可以是 常量,变量,也可以是表达式
  • Go语言中的switch语句中的case分支,结尾处不需要break(和其他编程语言有区别)
  • case后面表达式的数据类型,必须和switch的表达式一致
  • case后面的表达式可以是多个,使用逗号隔开
  • switch中default 也可以不需要
  • switch后面也可以没有表式,此种情况下整个switch结构和if...else..逻辑作用等同

示例1

package main

import "fmt"

func main(){
    var n int
    fmt.Println("please input number[1~7]: ")
    fmt.Scanln(&n)
    switch n {
    case 1:
        fmt.Println("Monday")
    case 2:
        fmt.Println("Tuesday")
    case 3:
        fmt.Println("Wednesday")
    case 4:
        fmt.Println("Thursday")
    case 5:
        fmt.Println("Friday")
    case 6:
        fmt.Println("Saturday")
    case 7 :
        fmt.Println("Sunday")
    default :
        fmt.Println("Unknown")
    }
}

$go run main.go
please input number[1~7]: 
7
Sunday

示例2

package main

import "fmt"

func main(){
    var n int
    fmt.Println("please input number[1~10]: ")
    fmt.Scanln(&n)
    switch n {
    case 2,4,6,8,10:
        fmt.Println("even number")
    case 1,3,5,7,9:
        fmt.Println("Odd number")
    default :
        fmt.Println("Unknown")
    }

}

示例3

package main

import "fmt"

func compareNum(x, y int) int {
    if x > y {
        return x
    } else if y > x {
        return y
    }
    return 0
}
func main() {
    var x int
    var y int
    fmt.Println("input two number x = ? and y = ?:")
    fmt.Scanln(&x, &y)
    switch {
    case compareNum(x, y) == x:
        fmt.Println("x is big")
    case compareNum(x, y) == y:
        fmt.Println("y is big")
    case compareNum(x, y) == 0:
        fmt.Println("x == y")
    }
}

$ go run main.go
input two number x = ? and y = ?:
90 90
x == y

fallthrough穿透 : 在case语句后面增加fallthrough会继续执行下一个case的内容

package main

import "fmt"

func main() {
    var passWorld string = "root123456"
    switch {
    case passWorld == "root123456":
        fmt.Println("passworld is ok")
        fallthrough
    case passWorld != "root123456":
        fmt.Println("passworld is error")
        fallthrough
    default:
        fmt.Println("passworld is null")
    }
}

$ go run main.go
passworld is ok
passworld is error
passworld is null

4. 循环控制-for

Go语言循环只支for关键字,不支持while和do...while结构

语法格式

for 循环变量初始化 ; 循环控制条件 ; 循环变量变化语句{

​ 循环体语句

}

  • 一般的for 循环中循环体不断的执行,直到循环控制条件不成立,for循环结束
  • for循环可以通过break ,goto,return,panic等语句退出循环
  • 无限循环也是通过for关键字实现,通常会配合一些结束条件

4.1 标准的for循环

package main

import "fmt"

func main(){
    // 求1到100整数的累加和
    // 写法1 标准的for循环写法
    var sum1 int = 0
    for i:=1;i<=100 ;i++  {
        sum1 += i
    }
    fmt.Println("写法1:从1累加到100的和是 : ",sum1)

    // 写法2
    var sum2 int = 0
    i := 1
    for i<=100{
        sum2 +=i
        i++
    }
    fmt.Println("写法2:从1累加到100的和是 : ",sum2)
    // 写法3
    var sum3 int = 0
    j := 1
    for ;;j++{
        if j>100{
            break
        }
        sum3 += j
    }
    fmt.Println("写法3:从1累加到100的和是 : ",sum3)

}

$ go run main.go
写法1:从1累加到100的和是 :  5050
写法2:从1累加到100的和是 :  5050
写法3:从1累加到100的和是 :  5050

4.2 for 无限循环

实现类似do..while

package main

import "fmt"

func main(){
    i:= 0
    for{
        if i>10{
            break
        }
        fmt.Println("i = ",i)
        i++
    }
}

$ go run main.go
i =  0
i =  1
i =  2
i =  3
i =  4
i =  5
i =  6
i =  7
i =  8
i =  9
i =  10

4.3 for 循环嵌套

package main

import "fmt"

func main() {
    // 打印一个九九乘法表
    for i := 1; i <= 9; i++ {
        for j := 1; j <= i; j++ {
            fmt.Printf("%d X %d = %d\t", j, i, i*j)
        }
        fmt.Println()
    }
}

$ go run main.go
1 X 1 = 1   
1 X 2 = 2   2 X 2 = 4   
1 X 3 = 3   2 X 3 = 6   3 X 3 = 9   
1 X 4 = 4   2 X 4 = 8   3 X 4 = 12  4 X 4 = 16  
1 X 5 = 5   2 X 5 = 10  3 X 5 = 15  4 X 5 = 20  5 X 5 = 25  
1 X 6 = 6   2 X 6 = 12  3 X 6 = 18  4 X 6 = 24  5 X 6 = 30  6 X 6 = 36  
1 X 7 = 7   2 X 7 = 14  3 X 7 = 21  4 X 7 = 28  5 X 7 = 35  6 X 7 = 42  7 X 7 = 49  
1 X 8 = 8   2 X 8 = 16  3 X 8 = 24  4 X 8 = 32  5 X 8 = 40  6 X 8 = 48  7 X 8 = 56  8 X 8 = 64  
1 X 9 = 9   2 X 9 = 18  3 X 9 = 27  4 X 9 = 36  5 X 9 = 45  6 X 9 = 54  7 X 9 = 63  8 X 9 = 72  9 X 9 = 81  

4.4 for-range 遍历

for循环配合for...range语句结构可以遍历字符串,数组,切片,map和通道(channel)

package main

import "fmt"

func main() {
    // for-range遍历
    // 遍历字符串
    var str string = "golang中国"
    fmt.Println("遍历字符串 :")
    for k, v := range str {
        fmt.Printf("%d==>%c\t", k, v)
    }
    //遍历数组
    var arr = [...]string{"one", "two", "three"}
    fmt.Printf("\n遍历数组 :\n")
    for k, v := range arr {
        fmt.Printf("%d==>%s\t", k, v)
    }
    // 遍历切片
    var sli []string = []string{"A", "B", "C"}
    fmt.Printf("\n遍历切片 :\n")
    for k, v := range sli {
        fmt.Printf("%d==>%s\t", k, v)
    }
    fmt.Printf("\n遍历map :\n")
    // 遍历map
    var personalInfo = map[string]string{
        "name":   "tom",
        "addr":   "beijing",
        "cardNo": "471823781238812389X",
    }
    for k, v := range personalInfo {
        fmt.Printf("%s:%s\n", k, v)
    }

}

$ go run main.go
遍历字符串 :
0==>g   1==>o   2==>l   3==>a   4==>n   5==>g   6==>中   9==>国   
遍历数组 :
0==>one 1==>two 2==>three   
遍历切片 :
0==>A   1==>B   2==>C   
遍历map :
addr:beijing
cardNo:471823781238812389X
name:tom

遍历channel

package main

import "fmt"

func main() {
    c := make(chan string)
    go func() {
        c<-"AA"
        c<-"BB"
        c<-"CC"
        c<-"DD"
        close(c)
    }()
    for v := range c{
        fmt.Println(v)
    }
}

$ go run main.go
AA
BB
CC
DD

5. 循环控制

5.1 break

break 语句可以结束for 的代码块,break 可以在后面添加标签,表示退出某个标签的代码块

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main(){
    // 初始化一个变量当做计数器
    count := 0
    for{
        rand.Seed(time.Now().UnixNano())
        n := rand.Intn(10000)+1
        fmt.Println("n = ",n)
        count++
        if n == 88{
            break
        }
    }
    fmt.Printf("生成88一共执行了%d次",count)
}

$ go run main.go
n =  88
生成88一共执行了468640次

break 通过标签指明要终止的语句块

  • break 默认跳出最近的for循环
  • break 指定跳出标签,跳出标签对应的for循环
package main

import "fmt"

func main() {
    LL_1:
    for i := 0; i < 5; i++ {
        fmt.Printf("i=%d\n",i)
        LL_2:
        for j := 0; j <= 10; j++ {
            fmt.Printf("\tj=%d\n",j)
            if i == 2{
                break LL_1
            }
            for k:=0;k<=10 ;k++  {
                fmt.Printf("\t\tk=%d\n",k)
                if  k == 3{
                    break LL_2
                }
            }
        }
    }
    fmt.Println("golang")
}

$ go run main.go
i=0
    j=0
        k=0
        k=1
        k=2
        k=3
i=1
    j=0
        k=0
        k=1
        k=2
        k=3
i=2
    j=0
golang

5.2 continue

continue语句表示跳出本次循环,进入下一个循环中

package main

import "fmt"

func main(){
    for i:=0;i<=10;i++{
        for j:=0;j<10;j++{
            if (i*j)%2==0{
                continue
            }
            fmt.Printf("%d * %d = %d\n",j,i,j*i)
        }
    }
}

continue 后面也可添加标签, 指明要跳过那一层循环

package main

import "fmt"

func main(){
    LOOP:
    for i:=0;i<=5;i++{
        for j:=0;j<5;j++{
            switch j {
            case  2:
                fmt.Println(i,j)
            continue LOOP
            }
        }
    }
}

$ go run main.go
0 2
1 2
2 2
3 2
4 2
5 2

6. 跳转

Go语言中goto语句可以直接跳转到指定的行

package main

import "fmt"

func main() {
    for i:= 0;i<20 ;i++{
        fmt.Println("Loop :",i)
        if i == 5{
            goto Here
        }
    }
    fmt.Println("A")
    fmt.Println("B")
    Here:
        fmt.Println("it is over")
    fmt.Println("main process is over")
}


$ go run main.go
Loop : 0
Loop : 1
Loop : 2
Loop : 3
Loop : 4
Loop : 5
it is over
main process is over

goto的一个应用场景 : 错误统一处理

package main

import (
    "errors"
    "fmt"
)

func checkError1()error{
    return errors.New("checkError_1 error")
}
func checkError2()error{
    return errors.New("checkError_2 error")
}
func main(){
    err := checkError1()
    if err != nil{
        goto operateError
    }
    err = checkError2()
    if err != nil{
        goto operateError
    }
    fmt.Println("program is ok")
    operateError:
        fmt.Println(err)
}

$ go run main.go
checkError_1 error
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352

推荐阅读更多精彩内容

  • Swift 提供了类似 C 语言的流程控制结构,包括可以多次执行任务的for和while循环,基于特定条件选择执行...
    穷人家的孩纸阅读 700评论 1 1
  • [The Swift Programming Language 中文版]本页包含内容: Swift提供了多种流程控...
    风林山火阅读 564评论 0 0
  • Swift提供了多种控制流声明。包括while循环来多次执行一个任务;if,guard和switch声明来根据确定...
    BoomLee阅读 1,944评论 0 3
  • 控制流 [TOC] Swift提供了多种流程控制结构,包括可以多次执行任务的while循环,基于特定条件选择执行不...
    伍哥___阅读 508评论 0 0
  • 49.8kg 早:鸡蛋50g,米糕80g,苹果150g 中午:牛肉80g,蔬菜米饭80g 晚:牛肉20g,蔬菜米饭...
    小时光_4ff1阅读 154评论 0 2