美文网首页
4. Go 程序结构控制

4. Go 程序结构控制

作者: PRE_ZHY | 来源:发表于2018-09-18 20:59 被阅读2次

当编写一个有一丢丢难度的程序的时候,就一定会涉及到程序结构(流向)的控制:需要一步一步顺序执行;需要根据不同情况进行选择,运行不同的代码;对相同的重复的事情,循环重复N次;两段代码同时运行,要可能要修改某一个变量值,但到底谁可以在什么时间、什么情况改需要精细控制。

在Go中,为了完成上述程序执行逻辑的控制,需要用的if, for, switch, func, select等内容,逐个来看。

顺序结构

Go 默认会按照顺序结构执行,即按照 main() 函数的语句的顺序,一条一条执行,直到执行碰到return 正常退出程序,或遇到程序异常,异常退出程序。当程序执行到函数main() 中遇到另外一个函数时,系统就会将main 函数的执行状态保存到一个叫”栈“的数据结构中,跳出main函数,去执行函数FuncA,在FuncA中遇到函数 FuncB 也一样。等函数FuncB 执行完成后,会返回FuncA,系统会从栈中找到FuncA 的信息并恢复,继续执行FuncA,知道FuncA返回,然后需要执行 main() 函数,直到 main() 完成,"交还"系统控制权。

函数调用结构.png

栈是一种数据结构,具有”先进后出“(FILO)这样的特性,更多细节可以参考维基百科

选择结构

当任务遇到不同的情况需要不同处理时,就需要用到 if 语句;当然还有其一家兄弟if..else if...else

if condition{

    /* true logic code */

} // condition满足就执行,否则不执行,执行下面的。
//最为常见的是错误处理,如果有错误就进行错误处理,没错误就继续

if condition{   

    /* true logic code */

}else {

    /* false logic code */

}// 条件满足就执行true逻辑,否则执行false逻辑。

if conditionA{

    /* A condition */ 

}else if conditionB{

    /*B condition */    

}else if conditionC{

    /*C condition */    

}else{

    /* other condition*/

}// 多条件就从上往下逐个执行,如果条件都不满足,就执行else。 
//还记得90-100评A,80-90评B,...吗?

if else 除了上述用法以外,还可以嵌套执行,就是如下的效果,用于复杂的条件判定。

if conditionA{
    if conditonA.1 {
        //A.1
    }else {
        //A.x(x!=1)
    }
}else{
    // !A
}

上述特性,其他语言一般都会提供,Go中还提供一种方式是if statement;conditon{} 其中 statement 是一个简短的声明或赋值,用于获取condition变量的值。与statement; if conditon{} 区别是什么呢?……作用域。作用域是一种表明变量或函数等可见范围与时间的描述。刚刚if语句中,如果statementif中,则statement中变量作用范围是该 if 块中,一旦离开if,就无法访问。而 statementif 外,则上下文对其变量都可以看到或修改。Go 中有一个原则,与含义不相关的简单变量使用简短名称定义,并且其作用域最小,这样就可以多处重复利用这些简短名称,且不会影响程序执行。最为常见到例子就是错误状态判断,在数据类型中map一节中,我们知道查询一个key会返回两个值,一个值本身,另外一个是值的状态。一个大的程序中有很多错误情况要判断,此时都可以通过 if value, ok := mapName[key];!ok{/*do something*/}

多选择结构

除了if...else外,还有一种选择结构叫 switch ,它通过用于很多个情况的选择,用来替代复杂的if...else if...elseif...elseswitch 一般情况下,是后面跟有一个变量,case condition 对变量取值进行判断,满足则执行,执行完当前条件,退出 switch; 如果除 default 外的条件都不满足,那就执行defalut语句,如果没有defalut语句,那就直接跳过 switch。如果一个语句可以应对多个condition,则可以使用逗号,将所有满足条件的罗列出来。

switch V{
    case conditonA:
        //statement
    case conditonB, conditonC, conditionD:
        //statemtnt
    case conditionE:
        // statement
    default:
        // statement
}

switch 还有一种特殊情况,就是没有变量 v ,那么变量可以直接在condition中表达,就更像if else

如果执行完第一个case,还想继续向下判断,那么可以通过 fallthrough 来继续测试后面的case条件,满足则再次执行

// 成绩score
switch {
    case score < 60 && score >= 60:
        fmt.Printf("不及格,D\n")
    case score >= 60:
        fmt.Printf("及格,")
        fallthrough
    case score >=70 && score < 80  :
        fmt.Println("C\n")
    case score >=80 && score < 90:
        fmt.Println("B\n")
    case score >=90 && score <= 100:
        fmt.Println("A\n")
    default:
        fmt.Println("录错成绩了,别激动!")
}

循环结构

循环,就是重复执行某一个需要重复的工作,例如一堆数据中找最大,或者单纯的想看看这个数据集。如果循环没没有退出条件的限制,最简单后果是CPU使用率一直很高,或者内存被消耗尽,也或者你设计良好,它默默的一直干活,总之设计循环退出条件是一件聪明的事情,可以在任意情况下选择退出,尽管你可以把退出条件设置的比较隐蔽。

Go 循环只有一种叫做for, 没有其他。for 结构:

for init;condition;post{
    /* do something */ 
}

其中 init为变量初始化条件,如果if 一样,在for 结构声明的变量,只能在该块中调用,初始化条件只执行一次;在初始化完成后,for 开始判断condition 是否满足,如果条件满足,则执行循环块;执行完循环后执行post 语句。然后继续检查条件是否满足,重复下去,直到条件不满足,退出循环条件。如果初始化条件声明在for 之外,初始化条件可以跳过;如果post语句在循环中执行,那么post 也可以省略;如果看到下面的循环中断关键字 break,可以用来手动判断是否退出,那么condition 也可以省略。

中断循环的关键字 break ,当程序执行到循环中的break 语句时,循环退出

跳出当前循环的关键字 continue, 当程序执行到循环中的 continue 时,循环剩下的语句将被跳过,执行post,开始下一次循环,计算循环条件。

package main

import  "fmt"

func main() {
    for i := 1; i <= 5; i++ {
        for j := 1; j <= i; j++ {
            if i == 4 && j == 2 {
                fmt.Printf("\t\t") //当碰到i=4,j=2的时候,则打印两个制表符
                continue // 跳出本地循环,即不打印下面 2x4=8这一项
            }
            fmt.Printf("%d x %d = %d\t", j, i, i*j)
        }
        fmt.Println()
    }
}
/* another
内部for循环还可以写为
--------------version 1-------------------
for i := 1; i <= 5; i++ {
        j := 1
        for ; j <= i; j++ { // 虽然省略了init,但是分号不可省,注意
            if i == 4 && j == 2 {
                fmt.Printf("\t\t")
                continue
            }
            fmt.Printf("%d x %d = %d\t", j, i, i*j)
        }
        fmt.Println()
    }
---------------version 2 -------------------
for i := 1; i <= 5; i++ {
        j := 1
        for j <= i {// 支持只有条件的for
            if i == 4 && j == 2 {
                fmt.Printf("\t\t")
                continue
            }
            fmt.Printf("%d x %d = %d\t", j, i, i*j)
            j++ // 还是要更新条件变量,否则真的时一直循环,直到死机或被系统强制结束
        }
        fmt.Println()
    }
--------------version 3 ------------------------
for i := 1; i <= 5; i++ {
        j := 1
        for { // 如果没有条件就一直循环,直到
            if j > i {
                break // 直到碰到break,break 可以通过if设置,如果没有if,那就没有循环
            }
            if i == 4 && j == 2 {
                fmt.Printf("\t\t")
                continue
            }
            fmt.Printf("%d x %d = %d\t", j, i, i*j)
            j++
        }
        fmt.Println()
    }
/* Result
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                       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
*/

需要注意的是,break只能退出当前循环,对于如上面嵌套循环,如果全部退出循环,则需要与嵌套循环数量完全一致的break语句。

这是一般程序结构控制,对于并发或者说多线程程序控制,更加复杂且难以预测。好消息是,Go 有原生并发支持,但不会再这一节展开。

相关文章

  • 4. Go 程序结构控制

    当编写一个有一丢丢难度的程序的时候,就一定会涉及到程序结构(流向)的控制:需要一步一步顺序执行;需要根据不同情况进...

  • 5.Golang流程控制

    一、程序结构说到流程控制,必须先看下 Go 语言的程序结构: 程序的初始化和执行都起始于 main package...

  • Go一些简要知识

    Go简要知识 1.程序结构 2.变量声明和赋值,三种格式 3.常量const 4.数字类型 5.Booleans:...

  • GO学习笔记(7) - 自建队列代码

    扩展已有类型的 程序结构 代码 go.mod queue/queue.go queue/entry/entry.go

  • 一个Go语言程序示例

    本文档介绍来自《Go语言编程》的简单Go语言程序示例。 程序结构 本程序是一个排序算法的实现,程序结构如下所示 创...

  • Go程序结构

    go 文件的后缀是 .go。 package main 表示该 hello.go 文件所在的包是 main, 在 ...

  • Go语言学习(1.1)

    程序结构 go语言标识符区分大小写 关键字:共25个 一些go内建的常量,变量,函数 Go语言通过标识符首字母大小...

  • Go语言 - 程序结构

    1 - 声明 go语言中有四个主要声明:变量( var ) - 常量( const ) - 类型( type )-...

  • Go基本程序结构

    编写测试程序 测试程序: 源码文件以_test结尾:x x x_test.go 测试方法名以Test开头:func...

  • Go学习-程序结构

    Go程序结构 命名 一个名字必须以字母或下划线开头;后面可以跟任意数量的字母、数字、下划线 区分字母大小写 变量的...

网友评论

      本文标题:4. Go 程序结构控制

      本文链接:https://www.haomeiwen.com/subject/voqvnftx.html