wx

关注公众号领取Go学习资料

wx

洋葱小店

2、基础篇(二):Go语言流程控制


For

Go只有一个循环结构,即for循环。

package main

import "fmt"

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

基本的for循环有三个用分号分隔的部分:

  • 初始化语句:在第一次迭代之前执行
  • 条件表达式:在每次迭代之前求值
  • 后置语句:在每次循环结束时执行

初始化语句通常是一个简短的变量声明,在那里声明的变量只在for语句的范围内可见。 一旦条件表达式的计算结果为false,循环将停止迭代。 注意:与C、Java或JavaScript等其他语言不同,for语句的三个组件周围没有括号,并且必须要有大括号{}。 初始化语句和后置语句是可选的。如下:

package main

import "fmt"

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

更进一步,还可以去掉分号:类似C语言中的的while那样,在Go中是用for实现的。如下:

package main

import "fmt"

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

如果省略循环条件,它将永远循环,因此一个死循环就可以这样写:

package main

func main() {
	for {
        // Do something forever
	}
}

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 {
		return v
	}
	return lim
}

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

(请尝试在最后一个return(line 12)语句中使用v。)

If and 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)
	}
	// can't use v here, though
	return lim
}

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

(在main中对fmt.Println的调用之前,会先对两个pow调用求值。)

练习:循环和函数

为了练习函数和方法,让我们实现一个平方根函数: 给定一个数字x,找到z²最接近x的数字z。 计算机通常使用循环计算x的平方根。从一些可能的z开始,我们可以根据z²与x的接近程度来调整z,从而产生更好的结果:

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

重复这种调整会使结果变得越来越好,直到我们得出尽可能接近实际平方根的答案 在函数Sqrt中实现这一功能。z的一个不错的起始值是1,无论输入是什么。首先,重复计算10次,并在计算过程中打印每个z。看看你离x(1,2,3,…)的各种值的答案有多近,以及猜测改进的速度有多快。 提示:要声明和初始化浮点值,请定义为浮点类型或使用类型转换转换:

z := 1.0
z := float64(1)

接下来,一旦值停止更改(或仅更改很小的量),就将循环条件更改为停止。看看这是多于还是少于10次迭代。尝试对z进行其他初始猜测,如x或x/2。您的函数的结果与标准库中的math.Sqrt有多接近? (注意:如果你对算法的细节感兴趣,上面的z²−x是z²离它需要的位置(x)有多远,除以2z是z²的导数,通过z²的变化速度来衡量我们调整z的程度。这种通用方法被称为牛顿方法。它适用于许多函数,但特别适用于平方根。) 以下代码仅供参考


import (
	"fmt"
	"math"
)

func Sqrt(x float64) float64 {
	var z = 1.0
	var old float64
	for math.Abs(old-z) >= 0.000001 {
		old = z
		z -= (z*z - x) / (2 * z)
	}
	return z
}

func main() {
	fmt.Println(Sqrt(2), math.Sqrt(2))
	fmt.Println(Sqrt(10), math.Sqrt(10))
}

Switch

switch语句是编写if-else的一种更简短的方法。它执行第一个满足条件的分支。

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.\n", os)
	}
}

Go的switch结构与C、C++、Java、JavaScript和PHP中的开关类似,只是Go只运行第一个符合条件的分支,而不是随后的所有案例。实际上,在Go中在每个分支最后都加了break语句。另一个重要的区别是Go的switch的分支条件不一定是常数,所涉及的值也不需要是整数。

执行顺序

switch 分支是从上到下进行判断的,当某一个分支成功时停止向下执行。例如:

switch i {
case 0:
case f():
}
// 如果i = 0 f函数是不执行的
package main

import (
	"fmt"
	"time"
)

func main() {
	fmt.Println("When's Saturday?")
	today := time.Now().Weekday()
	switch time.Saturday {
	case today + 0:
		fmt.Println("Today.")
	case today + 1:
		fmt.Println("Tomorrow.")
	case today + 2:
		fmt.Println("In two days.")
	default:
		fmt.Println("Too far away.")
	}
}

无条件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.")
	}
}

Defer

defer语句将一个函数的执行延迟到锁住函数返回时。延迟调用的参数会立即求值,但在周围的函数返回之前不会执行函数调用。

package main

import "fmt"

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

	fmt.Println("hello")
}

defer的函数调用被推送到堆栈中。当函数返回时,其defer调用将按后进先出的顺序执行。

package main

import "fmt"

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

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

	fmt.Println("done")
}
wx

关注公众号领取Go学习资料

wx

洋葱小店

©2017-2023 鲁ICP备17023316号-1 Powered by Hugo