流程控制
for
循环
- 循环语句中不用加
()
for
后面不跟随表达式
等价于JavaScript
中的while(true)
,此时语句中要有break/return
,不然会无限循环
Go
package main
import "fmt"
func testFor() {
k := 1
for {
if k > 3 {
break
}
fmt.Println("k的值为:", k);
k++
}
}
func main() {
testFor()
}
// 打印
// k的值为: 1
// k的值为: 2
// k的值为: 3
for
后面跟随一个表达式等价于JavaScript
中的while(condation)
Go
package main
import "fmt"
func testFor() {
i := 1
for i <= 3 {
fmt.Println("i的值为:", i)
i++
}
}
func main() {
testFor()
}
// 打印
// i的值为: 1
// i的值为: 2
// i的值为: 3
for
后面跟随3个表达式等价于JavaScript
中的for(初始化,判断,后续)
Go
package main
import "fmt"
func testFor() {
for f := 1; f <= 3; f++ {
fmt.Println("f的值为:", f)
}
}
func main() {
testFor()
}
// 打印
// f的值为: 1
// f的值为: 2
// f的值为: 3
if else
if else
语句中不推荐加()
if
后面跟随一个表达式等价于JavaScript
中的if(condition)
Go
package main
import "fmt"
func testIfElse() {
i := 6
if i > 5 {
fmt.Println("i的值大于5,i为:", i)
}
}
func main() {
testIfElse()
}
// 打印 i的值大于5,i为: 6
if
后面声明的变量,只能在if else
语句中才能访问到,外面访问不到
Go
package main
import "fmt"
func testIfElse() {
if f := 12; f >= 18 { // 相当于先声明一个变量f为12,再判断是否满足f>=18这个条件
fmt.Println("大于等于18岁,成年了")
} else if f > 10 {
fmt.Println("大于10岁,小于18岁")
} else {
fmt.Println("不到10岁")
}
// fmt.Println(f) 在if后面声明的变量,外部是拿不到的,只有if else 语句能拿到
}
func main() {
testIfElse()
}
// 打印 大于10岁,小于18岁
switch case
switch
语句中不加()
case
默认添加了break
语句,不用手动写,如果希望当前case
匹配到之后继续执行下一个case
的代码,使用fallthrough
case
后可以跟多个值
Go
package main
import (
"fmt"
"time"
)
func testSwitch() {
switch time.Now().Weekday() {
case time.Monday:
fmt.Println("周一")
case time.Tuesday:
fmt.Println("周二")
case time.Saturday, time.Sunday:
fmt.Println("周末")
default:
fmt.Println("周三到周五")
}
}
func main() {
testSwitch()
}
// 打印 周二
添加了fallthrough
Go
package main
import (
"fmt"
"time"
)
func testSwitch() {
switch time.Now().Weekday() {
case time.Monday:
fmt.Println("周一")
case time.Tuesday:
fmt.Println("周二")
fallthrough
case time.Saturday, time.Sunday:
fmt.Println("周末")
default:
fmt.Println("周三到周五")
}
}
func main() {
testSwitch()
}
// 打印
// 周二
// 周末
defer 延迟调用
defer
延迟调用函数
defer
语句后面跟着的函数会延迟到当前函数执行完后
再执行
Go
func deferFunc() {
fmt.Println("hello")
defer fmt.Println("defer后跟随的打印")
fmt.Println("go go go")
}
func main() {
// hello
// go go go
// defer后跟随的打印
deferFunc()
}
值的修改对defer
调用打印的影响
defer
只是延时调用函数,传递给函数里的值类型的变量
,不会受到后续程序的影响;引用类型
的变量打印会跟随修改;
Go
func deferVaribale() {
name := "张环"
defer fmt.Println("defer打印的name", name)
name = "李朗"
fmt.Println("name修改后为", name)
age := []int{22, 66, 88}
defer fmt.Println("defer打印的age", age)
age[1] = 99
fmt.Println("更新后的age为", age)
}
func main() {
// name修改后为 李朗
// 更新后的age为 [22 99 88]
// defer打印的age [22 99 88]
// defer打印的name 张环
deferVaribale()
}
延迟调用方法
defer
不仅能够延迟函数
的执行,也能延迟方法
的执行;
Go
type Reader interface {
read()
}
type Person struct {
name string
like string
}
func (p Person) read() {
fmt.Printf("%s喜欢%s\n", p.name, p.like)
}
func deferMethod() {
person := Person {
name: "张环",
like: "读书",
}
defer person.read()
fmt.Println("person 值为", person)
}
func main() {
// person 值为 {张环 读书}
// 张环喜欢读书
deferMethod()
}
defer
栈
- 当一个函数内多次调用
defer
时,Go
会把defer
调用放入到一个栈
中,随后按照先进后出
的顺序执行。
Go
func deferStack() {
fmt.Println("start")
defer fmt.Println("第一个defer打印")
defer fmt.Println("第二个defer打印")
defer fmt.Println("第三个defer打印")
defer fmt.Println("第四个defer打印")
defer fmt.Println("第五个defer打印")
defer fmt.Println("第六个defer打印")
fmt.Println("end")
}
func main() {
deferStack()
// start
// end
// 第六个defer打印
// 第五个defer打印
// 第四个defer打印
// 第三个defer打印
// 第二个defer打印
// 第一个defer打印
}
defer
栈作用域
- 当作用域为当前函数时,不同函数下有不同的
defer
栈
Go
func testDeferScope() {
func (){
defer fmt.Println("张环")
defer fmt.Println("李朗")
defer fmt.Println("沈韬")
}()
fmt.Println("-----------------")
func (){
defer fmt.Println(22)
defer fmt.Println(66)
defer fmt.Println(88)
}()
fmt.Println("=================")
}
func main() {
testDeferScope()
// 打印
// 沈韬
// 李朗
// 张环
// -----------------
// 88
// 66
// 22
// =================
}
defer
和return
和函数使用匿名返回值
Go
var str string = "张环"
func deferVal() string {
defer func(){
str = "李朗"
}()
fmt.Println("deferVal 函数内部的 str", str)
return str
}
func main() {
str_val := deferVal();
fmt.Println("deferVal函数返回值str_val", str_val)
fmt.Println("deferVal函数外部的str", str)
// 打印如下
// deferVal 函数内部的 str 张环
// deferVal函数返回值str_val 张环
// deferVal函数外部的str 李朗
}
defer
和return
和函数使用命名返回值
Go
func testDeferReturn() (num int) {
num = 10
defer func(){
num += 5
}()
return 2
}
func main() {
num := testDeferReturn()
fmt.Println(num) // 7
}
首先变量
num
作为返回值,初始值为0
其次,变量
num
被赋值为10
然后
return
时,变量num
被重新赋值为2
defer
在return
后执行,拿到变量num
将其修改为7
最终函数返回结果为
7
当defer
遇到panic
painc
时,已经声明的defer
会出栈执行,在panic
之后声明的defer
将不会执行
Go
func testDeferPanic() {
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
panic("------------")
defer fmt.Println(5) // 在panic之后声明的defer 将不会执行
}
func main() {
testDeferPanic()
// 打印
// 3
// 2
// 1
// panic: ------------
// 程序崩溃,没有打印5
}
使用recover
捕获panic
Go
func testCatchPanic() {
defer func (){
if err := recover(); err != nil {
fmt.Println( "程序崩溃原因:", err)
}
}()
panic("来,崩溃吧")
}
func main() {
testCatchPanic()
// 打印 程序崩溃原因: 来,崩溃吧
}
goto
无条件跳转
- 在
Go
语言中保留goto
,goto
后面接的是标签
,表示下一步要执行哪里的代码
Go
goto label_name
...
label_name: code
示例
Go
func baseGoTo() {
fmt.Println("start goto")
goto skip
fmt.Println("中间打印")
skip: fmt.Println("直接调转到这里")
}
func main() {
baseGoTo()
// 打印
// start goto
// 直接调转到这里
}
goto
语句与标签
之间不能有变量声明
Go
func testDefineVariable() {
fmt.Println("start goto")
goto define
fmt.Println("中间打印")
name := "sdf"
fmt.Println(name)
define: fmt.Println("直接调转到这里")
}
func main() {
// 运行报错 goto define jumps over declaration of name
testDefineVariable()
}