Listening to the Words

Go语言学习之流程控制

Go语言中最常用的流程控制有iffor,而switchgoto主要是为了简化代码、降低重复代码而生的结构,属于扩展类的流程控制。

相比于PHP,Go中的流程控制更加简洁,可选择的越少,编程规范越是更加统一,更加好维护

if else(分支结构)

不用说这是任何编程语言最常用的流程控制语句:

//这样精简的选择就是最好的
if condition1 {
    // do something 
} else if condition2 {
    // do something else    
} else {
    // catch-all or default
}

for循环

Go 语言中的所有循环类型均可以使用for关键字来完成。
PHP中有十分强大的foreach循环,Go中只提供了一个for

for循环的基本格式如下:

for 初始化语句; 条件语句; 修饰语句 {}

举例:

for i:=0;i<5;i++{
    fmt.Printf("This is the %d iteration\n", i)
}

还有更加简短(偷懒)的写法,但我觉得这种方式就足够了

while() 哪去了?

PHP中有while循环,如果达成某个条件就自动退出,Go中没有这个表达式该怎么办?

while ($i<=5){
    echo $i;
    $i++;
}

for循环照样可以解决这个问题:

func freeLoop() {
    i := 0
    for i < 10 {
        fmt.Println(i)
        i++
    }
}

是不是简单呢!

无限循环 (infinite loop )

监听服务器状态或者开启一个消费队列时都会用到无限循环,在PHP中实现如下:

// c语言 java也相似
for(;;){
    // todo
}
//或者直接使用while

while(true){
    // todo 
}

在Go中的实现则更加简单:

for{
    循环体语句
}

for循环可以通过breakgotoreturnpanic语句强制退出循环。

for range(go的foreach)

go中也提供了像PHP foreach()那么强大的遍历数组结构的循环语句

Go语言中可以使用for range遍历数组、切片、字符串、map 及通道(channel)。 通过for range遍历的返回值有以下规律:

  • 数组、切片、字符串返回索引和值。
  • map返回键和值。
  • 通道(channel)只返回通道内的值。
package main

import "fmt"

func main() {
    str := "Go is a beautiful language!"
    fmt.Printf("The length of str is: %d\n", len(str))
    for pos, char := range str {
        fmt.Printf("Character on position %d is: %c \n", pos, char)
    }
    fmt.Println()
    str2 := "Chinese: 日本語"
    fmt.Printf("The length of str2 is: %d\n", len(str2))
    for pos, char := range str2 {
        fmt.Printf("character %c starts at byte position %d\n", char, pos)
    }
    fmt.Println()
    fmt.Println("index int(rune) rune    char bytes")
    for index, rune := range str2 {
        fmt.Printf("%-2d      %d      %U '%c' % X\n", index, rune, rune, rune, []byte(string(rune)))
    }
}

输出的结果是:

The length of str is: 27
Character on position 0 is: G 
Character on position 1 is: o 
Character on position 2 is:   
Character on position 3 is: i 
Character on position 4 is: s 
Character on position 5 is:   
Character on position 6 is: a 
Character on position 7 is:   
Character on position 8 is: b 
Character on position 9 is: e 
Character on position 10 is: a 
Character on position 11 is: u 
Character on position 12 is: t 
Character on position 13 is: i 
Character on position 14 is: f 
Character on position 15 is: u 
Character on position 16 is: l 
Character on position 17 is:   
Character on position 18 is: l 
Character on position 19 is: a 
Character on position 20 is: n 
Character on position 21 is: g 
Character on position 22 is: u 
Character on position 23 is: a 
Character on position 24 is: g 
Character on position 25 is: e 
Character on position 26 is: ! 

The length of str2 is: 18
character C starts at byte position 0
character h starts at byte position 1
character i starts at byte position 2
character n starts at byte position 3
character e starts at byte position 4
character s starts at byte position 5
character e starts at byte position 6
character : starts at byte position 7
character   starts at byte position 8
character 日 starts at byte position 9
character 本 starts at byte position 12
character 語 starts at byte position 15

index int(rune) rune    char bytes
0       67      U+0043 'C' 43
1       104      U+0068 'h' 68
2       105      U+0069 'i' 69
3       110      U+006E 'n' 6E
4       101      U+0065 'e' 65
5       115      U+0073 's' 73
6       101      U+0065 'e' 65
7       58      U+003A ':' 3A
8       32      U+0020 ' ' 20
9       26085      U+65E5 '日' E6 97 A5
12      26412      U+672C '本' E6 9C AC
15      35486      U+8A9E '語' E8 AA 9E

switch case

Go语言规定每个switch只能有一个default分支。

func switchDemo1() {
    finger := 3
    switch finger {
    case 1:
        fmt.Println("大拇指")
    case 2:
        fmt.Println("食指")
    case 3:
        fmt.Println("中指")
    case 4:
        fmt.Println("无名指")
    case 5:
        fmt.Println("小拇指")
    default:
        fmt.Println("无效的输入!")
    }
}

一个分支可以有多个值,多个case值中间使用英文逗号分隔。

func testSwitch3() {
    switch n := 7; n {
    case 1, 3, 5, 7, 9:
        fmt.Println("奇数")
    case 2, 4, 6, 8:
        fmt.Println("偶数")
    default:
        fmt.Println(n)
    }
}

分支还可以使用表达式,这时候switch语句后面不需要再跟判断变量。例如:

func switchDemo4() {
    age := 30
    switch {
    case age < 25:
        fmt.Println("好好学习吧")
    case age > 25 && age < 35:
        fmt.Println("好好工作吧")
    case age > 60:
        fmt.Println("好好享受吧")
    default:
        fmt.Println("活着真好")
    }
}

fallthrough语法可以执行满足条件的case的下一个case,是为了兼容C语言中的case设计的。

func switchDemo5() {
    s := "a"
    switch {
    case s == "a":
        fmt.Println("a")
        fallthrough
    case s == "b":
        fmt.Println("b")
    case s == "c":
        fmt.Println("c")
    default:
        fmt.Println("...")
    }
}
输出:
a
b

goto

goto语句十分跳跃其实更加不利于程序阅读和维护,因此很少使用goto语句

点赞