Go进阶之路——流程控制语句

for

Go 只有一种循环结构——`for` 循环。

基本的 for 循环除了没有了 `( )` 之外(甚至强制不能使用它们),看起来跟 C 或者 Java 中的一样,而 `{ }` 是必须的。

package main

import "fmt"

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

跟 C 或者 Java 中一样,也可以让前置、后置语句为空。

package main

import "fmt"

func main() {
	sum := 1
	for ; sum < 1000; {
		sum += sum
	}
	fmt.Println(sum)
}

这种方式可以取代C和Java中的while循环方式。

也可以使用 for..range 对数组、切片、map、 字符串等进行循环操作,例如:

package main

import "fmt"

func main() {
    numbers := []int{1, 2, 3}

    for i, v := range numbers {
        fmt.Printf("numbers[%d] is %d\n", i, v)
    }
}

 注意: 这里的 iv 是切片元素的位置索引和值。

可以通过赋值给 _ 来忽略序号和值。

如果只需要索引值,去掉“, v”的部分即可。

package main

import "fmt"

func main() {
    cityCodes := map[string]int{
        "北京": 1,
        "上海": 2,
    }

    for i, v := range cityCodes {
        fmt.Printf("%s is %d\n", i, v)
    }
}

注意: 这里的 iv 是 map 的 一组键值对的键和值。

 Go同样也可以使用 continue 和 break 对循环进行控制,例如:

package main

import "fmt"

func main() {
    numbers := []int{1, 2, 3, 4, 5}

    for i, v := range numbers {
        if v == 4 {
            break
        }

        if v%2 == 0 {
            continue
        }

        fmt.Printf("numbers[%d] is %d\n", i, v)
    }
}

死循环

如果省略了循环条件,循环就不会结束,因此可以用更简洁地形式表达死循环。

package main

func main() {
	for {
	}
}

if

if 语句除了没有了 `( )` 之外(甚至强制不能使用它们),看起来跟 C 或者 Java 中的一样,而 `{ }` 是必须的。

package main

import (
	"fmt"
	"math"
)

func sqrt(x float64) string {
	if x < 0 {
		return sqrt(-x) + "i"
	}
	return fmt.Sprint(math.Sqrt(x))
}

func main() {
	fmt.Println(sqrt(2), sqrt(-4))
}

还可以使用 if..else if..else 来实现多分支的条件判断:

package main

import "fmt"

func main() {
    age := 13

    if age > 6 && age <= 12 {
        fmt.Println("It's primary school")
    } else if age > 12 && age <= 15 {
        fmt.Println("It's middle school")
    } else {
        fmt.Println("It's high school")
    }
}

跟 for 一样,`if` 语句可以在条件之前执行一个简单的语句(if 的便捷语句)。

由这个语句定义的变量的作用域仅在 if 范围之内。

package main

import (
	"fmt"
	"math"
)

func pow(x, n, lim float64) float64 {
	if v := math.Pow(x, n); v < lim {
		return v
	}
	return lim
}

func main() {
	fmt.Println(
		pow(3, 2, 10),
		pow(3, 3, 20),
	)
}

在 if 的便捷语句定义的变量同样可以在任何对应的 else 块中使用。

package main

import (
	"fmt"
	"math"
)

func pow(x, n, lim float64) float64 {
	if v := math.Pow(x, n); v < lim {
		return v
	} else {
		fmt.Printf("%g >= %g\n", v, lim)
	}
	// 这里开始就不能使用 v 了
	return lim
}

练习例子:

用牛顿法实现开方函数。

牛顿法是通过选择一个初始点 z 然后重复这一过程求 Sqrt(x) 的近似值:

 

package main

import (
	"fmt"
	"math"
)

func Sqrt(x float64) float64 {
	z := float64(1)
	for {
		temp := z - (z*z-x)/(2*z)
		if temp==z || (temp>z && temp-z<0.00000001) || (temp

输出结果:

switch

如果我们的条件分支太多,可以考虑使用 switch 替换 if, 例如:

package main

import "fmt"

func main() {
    age := 10

    switch age {
    case 5:
        fmt.Println("The age is 5")
    case 7:
        fmt.Println("The age is 7")
    case 10:
        fmt.Println("The age is 10")
    default:
        fmt.Println("The age is unkown")
    }
}

同if,switch后也可以添加一个简单的语句

package main

import (
	"fmt"
	"runtime"
)

func main() {
	fmt.Print("Go runs on ")
	switch os := runtime.GOOS; os {
	case "darwin":
		fmt.Println("OS X.")
	case "linux":
		fmt.Println("Linux.")
	default:
		// freebsd, openbsd,
		// plan9, windows...
		fmt.Printf("%s.", os)
	}
}

ps:GOOS是可执行程序的目标操作系统(将要在该操作系统的机器上执行):darwin、freebsd、linux等。

注意:在 Go 中 switch 只要匹配中了就会中止剩余的匹配项,直接跳出整个switch,这和 Java 很大不一样,java需要使用 break 来主动跳出。

但是可以使用 fallthrough 强制执行后面的case代码。

switch {
    case false:
        fmt.Println("The integer was <= 4")
        fallthrough
    case true:
        fmt.Println("The integer was <= 5")
        fallthrough
    case false:
        fmt.Println("The integer was <= 6")
        fallthrough
    case true:
        fmt.Println("The integer was <= 7")
        fallthrough
    case false:
        fmt.Println("The integer was <= 8")
    default:
        fmt.Println("default case")
    }

但也要注意,fallthrough 不能用在switch的最后一个分支。

switch 的 case 条件可以是多个值,例如:

package main

import "fmt"

func main() {
    age := 7

    switch age {
    case 7, 8, 9, 10, 11, 12:
        fmt.Println("It's primary school")
    case 13, 14, 15:
        fmt.Println("It's middle school")
    case 16, 17, 18:
        fmt.Println("It's high school")
    default:
        fmt.Println("The age is unkown")
    }
}

注意: 同一个 case 中的多值不能重复。

没有条件的 switch

没有条件的 switch 同 `switch true` 一样。

这一构造使得可以用更清晰的形式来编写长的 if-then-else 链。

package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Now()
	switch {
	case t.Hour() < 12:
		fmt.Println("Good morning!")
	case t.Hour() < 17:
		fmt.Println("Good afternoon.")
	default:
		fmt.Println("Good evening.")
	}
}

小技巧: 使用 switch 对 interface{} 进行断言,例如:

package main

import "fmt"

func checkType(i interface{}) {
    switch v := i.(type) {
    case int:
        fmt.Printf("%v is an in\n", v)
    case string:
        fmt.Printf("%v is a string\n", v)
    default:
        fmt.Printf("%v's type is unkown\n", v)
    }
}

func main() {
    checkType(8)
    checkType("hello, world")
}

defer

defer 语句会延迟函数的执行直到上层函数返回。

延迟调用的参数会立刻生成,但是在上层函数返回前函数都不会被调用。

package main

import "fmt"

func main() {
	defer fmt.Println("world")

	fmt.Println("hello")
}

输出结果:

defer 栈

延迟的函数调用被压入一个栈中。当函数返回时, 会按照后进先出的顺序调用被延迟的函数调用。

package main

import "fmt"

func main() {
	fmt.Println("counting")

	for i := 0; i < 10; i++ {
		defer fmt.Println(i)
	}

	fmt.Println("done")
}

输出结果:

Go进阶之路——流程控制语句_第1张图片

更多了解https://blog.golang.org/defer-panic-and-recover

你可能感兴趣的:(Go)