Go的流程控制

流程控制

Go语言支持最基本的三种程序运行结构:顺序结构、选择结构、循环结构。

  • 顺序结构:程序按顺序执行,不发生跳转。
  • 选择结构:依据是否满足条件,有选择的执行相应功能。
  • 循环结构:依据条件是否满足,循环多次执行某段代码。

1 选择结构

1.1 if语句

1.1.1 if条件判断基本写法
package main

import "fmt"

func main(){
    s := "屌丝"
    // if 和{ 就是条件,条件通常都是关系运算符
    if s == "王思聪"{  //左括号和if在同一行
        fmt.Println("左手一个妹纸,右手一个大妈")
    }

    // if 支持一个初始化语句,初始化语句和判断条件以分号隔开
    if a := 10; a == 10 {  //条件为真,指向{}语句
        fmt.Println("a==10")

    }
}
1.1.2 if ... else和if...else if ...else
package main

import "fmt"

func main(){
    //1
    a := 2
    if a == 10{
        fmt.Println("a == 10")
    } else { // else后面没有条件
        fmt.Println("a != 10")
    }

    // 2
    if a:=10; a == 10{
        fmt.Println("a == 10")
    }else{
        fmt.Println("a != 10")
    }

    if a:=20; a == 10{
        fmt.Println("a == 10")
    }else if a > 10{
        fmt.Println("a > 10")
    }else if a < 10{
        fmt.Println("a < 10")
    }else{
        fmt.Println("这是不可能的")
    }
}

注意点:对于if...else if....else可以使用if 来替代,但是通常不会用

package main

import "fmt"

func main(){
    if a:=10;a == 10{
        fmt.Println("a == 10")
    }else if a>10{
        fmt.Println("a>10")
    }else if a<10{
        fmt.Println("a<10")
    }

    var b = 10
    if b==10{
        fmt.Println("b==10")
    }
    if b>10 {
        fmt.Println("b>10")
    }
    if b<10{
        fmt.Println("b<10")
    }
}

两个判断的执行结果一致,但是遇到这种场景,不会选择第二种,因为第二种要逐条判断,第一种如果第一个条件满足,后面的代码不会执行。

1.2 switch语句

Go里面switch默认相当于每个case最后带有break,匹配成功后不会自动向下执行其他case,而是跳出整个switch, 但是可以使用fallthrough强制执行后面的case代码:
package main

import "fmt"

func main(){
    num := 10

    switch num {  //switch后面写的是变量本身
    case 1:
        fmt.Println("按下的是1楼")
        break  // go语言保留了break关键字,跳出switch,不写,默认包含
    case 2:
        fmt.Println("按下的是2楼")
    case 3:
        fmt.Println("按下的是3楼")
    case 4:
        fmt.Println("按下的是4楼")
    case 5:
        fmt.Println("按下的是5楼")
    default:
        fmt.Printf("按下的是xxx楼")
    }
}

如果使用fallthrough关键字,它表示不跳出switch,会将后面所有的case代码全部执行

package main

import "fmt"

func main(){
    var num int
    fmt.Printf("请按下楼层:")
    fmt.Scan(&num)
    switch num {
    case 1:
        fmt.Println("按下的是1楼")
        fallthrough
    case 2:
        fmt.Println("按下的是2楼")
        fallthrough
    case 3:
        fmt.Println("按下的是3楼")
        fallthrough
    case 4:
        fmt.Println("按下的是4楼")
        fallthrough
    default:
        fmt.Printf("按下的XXX楼")
    }
}

一个case后面可以跟多个条件,switch后面也可以不用跟变量

package main

import "fmt"

func main(){
    // 支持一个初始化语句,初始化语句和变量本身,以分号分割
    switch num:=5; num {
    case 1:
        fmt.Println("按下的是1楼")
    case 2:
        fmt.Println("按下的是2楼")
    case 3,4,5:   // 可以跟多个条件
        fmt.Println("按下的是yyyy楼")
    default:
        fmt.Println("按下的是xxxxx楼")
    }


    score := 85
    switch {  //可以没有条件
    case score > 90:  //case 后面可以放条件
        fmt.Println("优秀")
    case score > 80:
        fmt.Println("良好")
    case score > 70:
        fmt.Println("一般")
    default:
        fmt.Println("其他")
    }
}

2 循环语句

2.1 for

在go语言中只有for循环,语法为: for 初始化条件; 判断条件; 条件变化{}

package main

import "fmt"

func main(){
    // for 初始化条件; 判断条件; 条件变化{
    // }
    // 1+2+3+……+100
    sum := 0

    //1.初始化条件 i:=1
    //2.判断条件是否为真,i<=100; 如果为真,执行循环体,如果为假,跳出
    //3.条件变化 i++
    //4.重复2,3,4
    for i:=1; i<=100; i++{
        sum += i
    }
    fmt.Println("sum = ", sum)
}

使用python实现上述例子:

# for 循环
sum = 0
for i in range(101):
    sum += i
print(sum)


# while循环
i = 0
sum1 = 0
while 1:
    sum1 += i
    if i == 100:
        break
    i += 1
print(sum1)

python和go在循环上的语法区别还是很大的,要加以区分。

在go语言中,for后面不加任何东西,相当于python中的while 1

练习:使用python和go分别实现99表

# python
# for 版本 for i in range(1,10): for j in range(1,i+1): print("%d * %d = %d" % (j, i, i*j), end=" ") print("") # while 版本 n = 1 sum = 1 while n <= 9: i = 1 while i <= n: sum = i * n print("%d * %d = %d" %(n, i, sum), end=" ") i += 1 print("") n += 1
//go版本
package main import "fmt" func main() { for i:=1; i<=9; i ++{ for j:=1; j<=i; j++{ fmt.Printf("%d * %d = %d\t" , j, i, i*j) } fmt.Printf("\n") } }

2.2 range

关键字 range 会返回两个值,第一个返回值是元素的数组下标,第二个返回值是元素的值:

package main

import "fmt"

func main(){
    str := "abc"
    // 通过for循环打印每个字符
    for i:=0; i<len(str); i++{
        fmt.Printf("str[%d] = %c\n", i, str[i])
    }

    // 迭代打印每个元素,默认返回两个值,一个是元素的索引,一个是元素的本身
    for i, data := range str{  //支持 string/array/slice/map。
        fmt.Printf("str[%d]=%c\n", i, data)
    }

    for i:=range str{ // 第二个返回值,默认丢弃,返回元素的索引位置
        fmt.Printf("str[%d] = %c\n", i, str[i])
    }

    for i,_:=range str{  // 第二个返回值,通过匿名变量丢弃,返回元素的索引位置
        fmt.Printf("str[%d] = %c\n", i, str[i])
    }
 }

注意:python range() 函数可创建一个整数列表,一般用在 for 循环中。

3 跳转语句

3.1 break和continue

在循环里面有两个关键操作break和continue,break操作是跳出当前循环,continue是跳过本次循环。(和python中用法一致)

注意:break可于for、switch、select,continue仅能用于for循环。

package main
import (
"time"
"fmt"
)
func main() {
i := 0
for {
i ++
time.Sleep(time.Second) //延时1秒
if i == 5{
break // 跳出循环,如果嵌套多个循环,跳出最近的那个内循环
// continue //跳出本次循环下次继续
}
fmt.Println("i = ", i)
}
}

break语句还可以在语句后面添加标签,表示退出某个标签对应的代码块,标签要求必须定义在对应的for,switch和select的代码块上。举个例子:

func breakDemo(){
BREAKDEMO1:
    for i:=0;i<10;i++{
        for j:=0;j<10;j++{
            if j==2{
                break BREAKDEMO1
            }
            fmt.Printf("%v-%v\n",i,j)
        }
    }  
    fmt.Println("...")
}    

continue语句可以结束当前循环,开始下一次的循环迭代过程,仅限在for循环内使用。

在continue语句后添加标签后,表示开始标签对应的循环,例如:

func continueDemo() {
forloop1:
    for i := 0; i < 5; i++ {
        // forloop2:
        for j := 0; j < 5; j++ {
            if i == 2 && j == 2 {
                continue forloop1
            }
            fmt.Printf("%v-%v\n", i, j)
        }
    }
}

3.2 goto

用goto跳转到必须在当前函数内定义的标签:

package main

import "fmt"

func main()  {
    //break  //break is not in a loop, switch, or select
    //continue  //continue is not in a loop
    // goto可以用在任何地方,但是不能跨函数使用

    fmt.Println("11111111111111")

    goto End   // goto是关键字,End是用户起的标签
    
    fmt.Println("22222222222222")

    End:
        fmt.Println("333333333333333333333")

}