for 循环

Go 只有一种循环结构:for 循环。

基本的 for 循环由三部分组成,用分号隔开:

  • 初始化语句:在每一次迭代前执行
  • 条件表达式:在每次迭代前求值
  • 后置语句:在每次迭代的结尾执行

初始化语句通常为通常为一句短变量声明 := ,该变量声明仅在 for 语句的作用域中可见,与其他语言一样,初始化语句和后置语句都是可选的。

与 Java 最大的不同是,Go 的 for 语句后面的三个构成部分外没有小括号。

代码例子:

package main

import "fmt"

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

Go 语言中没有 while 关键字,for 就是 Go 中的 while。具体做法就是去掉分号,只保留条件表达式。

代码例子:

package main

import "fmt"

func main() {
    sum := 1
    for sum < 100 {   
        sum += sum
    }
    fmt.Printf(sum)
}

if 判断

Go 的 if 语句与 for 循环类似,表达式外无需小括号 ( ),而大括号 { } 是必须的。

示例代码:

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))
}

和 for 循环一样,在条件表达式前 if 也可以加入一个简短语句做初始化

该语句声明的变量作用域仅在 if 之内

示例代码:

package main

import (
    "fmt"
    "math"
)

func pow(x, n, lim float64) float64 {
    if v := math.Pow(x, n); v < lim {
        // math.Pow(x, n) 是求 x 的 n 次幂
        return v
    }
    return lim
}

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

在 if 的条件表达式前加入的简短语句中声明的变量可以在该 if 对应下的 else 块中使用,但是超出 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)  
    }
    return lim
}

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

练习题:循环与函数

实现一个平方根函数:给定一个数 x,需要找到一个数 z 使得 z2 尽可能接近 x 。

实现思想是从某个猜测的值 z 开始,根据 z2 与 x 的近似度来改进 z ,迭代公式如下:

z -= (z * z - x) / (2 * z)

插一句:牛顿迭代法的思想是 计算 z2 与 x 的距离,除以 z2 的导数,通过 z2 的变化速度来改变 z 的调整

重复迭代,使结果越来越接近实际的平方根。初始值 z 从 1.0 开始,迭代 10 轮,打印 z 的结果。

然后修改循环条件,使得当值改变的非常小(设置差值阈值为 10e-6 )时退出循环。最终测试一下迭代结果与标准库的 math.Sqrt() 的差距是多少?

示例代码:

package main

import (
	"fmt"
	"math"
)

func Sqrt(x float64) float64 {
	z := 1.0
	preZ := 0.0
	for i := 0; i < 10; i++ {
		preZ = z
		z -= (z*z - x) / (2 * z)
		fmt.Printf("Iteration %d: z = %v\n", i+1, z)
		if diff := preZ - z; diff < 10e-6 && diff > -10e-6 {
			break
		}
	}
	return z
}

func main() {
	fmt.Printf("最终结果:%f\n", Sqrt(2))
	fmt.Printf("差距:%f", Sqrt(2) - math.Sqrt(2))
}

defer 推迟

defer 语句会将函数推迟到外层函数返回之后再执行。

推迟调用的函数其参数会立即求值,但直到外层函数返回前该函数都不会被调用。

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

示例代码:

package main

import (
    "fmt"
)

func main() {
    fmt.Println("counting")
    for i := 0; i < 10; i++ {
        defer fmt.Println(i)
    }
    fmt.Println("done")
}

返回结果:

Categories:

Tags:

No responses yet

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注