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")
}
返回结果:


No responses yet