第13节 Go语言退出、结束函数或者协程方式
❤️💕💕Go语言高级篇章,在此之前建议您先了解基础和进阶篇。Myblog:http://nsddd.top
Go语言基础篇
Go语言100篇进阶
[TOC]
提示
Go语言中有很多让我觉得误解的一些终结语句,我想 block
和 continue
只是最基本的也是最简单的。
Go语言几种退出程序的方式:
os.Exit()
退出程序panic()
抛出异常return
退出函数defer + recover()
捕获异常runtime.Goexit()
退出当前协程os.Kill
杀死进程os.Interrupt
中断进程block
跳出循环 (不讲)continue
跳出当前循环 继续下一次循环 (不讲)
runtime.Goexit() 退出当前协程
💡简单的一个案例如下:
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
//Go语言几种退出程序的方式
//1. os.Exit() 退出程序
//2. panic() 抛出异常
//3. return 退出函数
//4. defer + recover() 捕获异常
//5. runtime.Goexit() 退出当前协程
//6. os.Kill 杀死进程
//7. os.Interrupt 中断进程
//8. block 跳出循环
//9. continue 跳出当前循环 继续下一次循环
fmt.Println("main() 开始的部分")
go func() {
fmt.Println("go func() 开始的部分")
func() {
fmt.Println("func() 开始的部分")
go func() {
fmt.Println("最里面go func() 开始的部分")
runtime.Goexit() //退出当前协程
fmt.Println("最里面go func() 结束的部分")
}()
fmt.Println("func() 结束的部分")
//等待2s
time.Sleep(2 * time.Second)
}()
fmt.Println("go func() 结束的部分")
}()
//等待5s
time.Sleep(time.Second * 5)
fmt.Println("main() 结束的部分")
}
🚀 编译结果如下:
[Running] go run "d:\文档\最近的\awesome-golang\docs\code\go-super\61-main.go"
main() 开始的部分
go func() 开始的部分
func() 开始的部分
最里面go func() 开始的部分
func() 结束的部分
go func() 结束的部分
main() 结束的部分
📜 对上面的解释:
runtime.Goexit() //退出当前协程
只是退出当前的 go func()
协程,并不是当前函数。
os.Exit(-1) 退出当前程序
函数定义:
函数定义:func Exit(code int)
Exit 函数可以让当前程序以给出的状态码 code
退出。一般来说,状态码 0
表示成功,非 0
表示出错。程序会立刻终止,并且 defer
的函数不会被执行。
package main
import (
"fmt"
"os"
)
func main() {
var num int = 0
fmt.Printf("Enter number:")
fmt.Scanf("%d", &num)
if num > 0 {
fmt.Printf("n > 0 Program terminated\n")
os.Exit(0)
} else if num < 0 {
fmt.Printf("n < 0 Program continue\n")
}
fmt.Printf("Program finished normally\n")
}
🚀 编译结果如下:
PS D:\文档\最近的\awesome-golang\docs\code\go-super> go run .\66-main.go
Enter number:2
n > 0 Program terminated
PS D:\文档\最近的\awesome-golang\docs\code\go-super> go run .\66-main.go
Enter number:-1
n < 0 Program continue
Program finished normally
PS D:\文档\最近的\awesome-golang\docs\code\go-super> go run .\66-main.go
Enter number:0
Program finished normally
💡简单的一个案例如下:
package main
import (
"fmt"
"os"
"time"
)
func main() {
fmt.Println("main() 开始的部分")
go func() {
fmt.Println("go func() 开始的部分")
func() {
fmt.Println("func() 开始的部分")
go func() {
fmt.Println("最里面go func() 开始的部分")
os.Exit(-1) //退出程序
fmt.Println("最里面go func() 结束的部分")
}()
//等待2s
time.Sleep(2 * time.Second)
fmt.Println("func() 结束的部分")
}()
fmt.Println("go func() 结束的部分")
}()
//等待5s
time.Sleep(time.Second * 5)
fmt.Println("main() 结束的部分")
}
🚀 编译结果如下:
[Running] go run "d:\文档\最近的\awesome-golang\docs\code\go-super\61-main.go"
main() 开始的部分
go func() 开始的部分
func() 开始的部分
最里面go func() 开始的部分
exit status 0xffffffff
📜 对上面的解释:
os.Exit(-1) //退出程序
退出当前的 func main()
程序
os.Exit(0) 中断进程
💡简单的一个案例如下:
package main
import (
"fmt"
"os"
"time"
)
func main() {
fmt.Println("main() 开始的部分")
go func() {
fmt.Println("go func() 开始的部分")
func() {
fmt.Println("func() 开始的部分")
go func() {
fmt.Println("最里面go func() 开始的部分")
//中断进程
os.Exit(0)
fmt.Println("最里面go func() 结束的部分")
}()
//等待2s
time.Sleep(2 * time.Second)
fmt.Println("func() 结束的部分")
}()
fmt.Println("go func() 结束的部分")
}()
//等待5s
time.Sleep(time.Second * 5)
fmt.Println("main() 结束的部分")
}
🚀 编译结果如下:
[Running] go run "d:\文档\最近的\awesome-golang\docs\code\go-super\63-main.go"
main() 开始的部分
go func() 开始的部分
func() 开始的部分
最里面go func() 开始的部分
📜 对上面的解释:
状态码为 0 ,退出但是不报错
panic() 抛出异常退出
或许你可以使用defer func() 抛出异常继续执行
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println("main() 开始的部分")
go func() {
fmt.Println("go func() 开始的部分")
func() {
fmt.Println("func() 开始的部分")
go func() {
fmt.Println("最里面go func() 开始的部分")
//defer异常捕获
defer func() {
if err := recover(); err != nil {
fmt.Println("最里面go func() defer异常捕获", err)
}
}()
panic("最里面go func() 抛出异常退出")
fmt.Println("最里面go func() 结束的部分")
}()
//等待2s
time.Sleep(2 * time.Second)
fmt.Println("func() 结束的部分")
}()
fmt.Println("go func() 结束的部分")
}()
//等待5s
time.Sleep(time.Second * 5)
fmt.Println("main() 结束的部分")
}
🚀 编译结果如下:
[Running] go run "d:\文档\最近的\awesome-golang\docs\code\go-super\61-main.go"
main() 开始的部分
go func() 开始的部分
func() 开始的部分
最里面go func() 开始的部分
最里面go func() defer异常捕获 最里面go func() 抛出异常退出
func() 结束的部分
go func() 结束的部分
main() 结束的部分
💡简单的一个案例如下:
package main
import (
"fmt"
"time"
)
func main() {
//Go语言几种退出程序的方式
//1. os.Exit() 退出程序
//2. panic() 抛出异常
//3. return 退出函数
//4. defer + recover() 捕获异常
//5. runtime.Goexit() 退出当前协程
//6. os.Kill 杀死进程
//7. os.Interrupt 中断进程
//8. block 跳出循环
//9. continue 跳出当前循环 继续下一次循环
fmt.Println("main() 开始的部分")
go func() {
fmt.Println("go func() 开始的部分")
func() {
fmt.Println("func() 开始的部分")
go func() {
fmt.Println("最里面go func() 开始的部分")
panic("最里面go func() 抛出异常退出")
fmt.Println("最里面go func() 结束的部分")
}()
//等待2s
time.Sleep(2 * time.Second)
fmt.Println("func() 结束的部分")
}()
fmt.Println("go func() 结束的部分")
}()
//等待5s
time.Sleep(time.Second * 5)
fmt.Println("main() 结束的部分")
}
🚀 编译结果如下:
[Running] go run "d:\文档\最近的\awesome-golang\docs\code\go-super\61-main.go"
main() 开始的部分
go func() 开始的部分
func() 开始的部分
最里面go func() 开始的部分
panic: 最里面go func() 抛出异常退出
goroutine 7 [running]:
main.main.func1.1.1()
d:/文档/最近的/awesome-golang/docs/code/go-super/61-main.go:28 +0x65
created by main.main.func1.1
d:/文档/最近的/awesome-golang/docs/code/go-super/61-main.go:25 +0x65
exit status 2
📜 对上面的解释:
可以看出来这两者之间的差距,recover()
使得 程序结束当前协程~继续执行使用。
不使用的化,会直接退出~
return 跳出当前函数
return 是我们最常用的一个用法:在设定返回值为1002,然后return触发defer语句,执行完成后(即便是defer抛出panic后被捕获),返回1002。
我们都知道 panic
会触发defer
: 由于 return
会触发 defer
,函数抛出 panic
也会触发 defer
。所以我们可以在 defer
中,特别是通过 recovery()
函数捕获 panic
后,修改函数的返回值。
func main() {
fmt.Println(Test0())
}
func Test0()(ret string){
defer func() {
err:=recover()
if err!=nil{
ret=fmt.Sprint(err)
}
}()
panic("this is a panic")
return "normal"
}
🚀 编译结果如下:
this is a panic
📜 对上面的解释:
注意 panic
和 return
的循序很重要,如果当 return "normal"
在前面,那么很明显会输出 normal
,this is a panic
将不会输出。
💡简单的一个案例如下:
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println("main() 开始的部分")
go func() {
fmt.Println("go func() 开始的部分")
func() {
fmt.Println("func() 开始的部分")
go func() {
fmt.Println("最里面go func() 开始的部分")
return
fmt.Println("最里面go func() 结束的部分")
}()
//等待2s
time.Sleep(2 * time.Second)
fmt.Println("func() 结束的部分")
}()
fmt.Println("go func() 结束的部分")
}()
//等待5s
time.Sleep(time.Second * 5)
fmt.Println("main() 结束的部分")
}
🚀 编译结果如下:
[Running] go run "d:\文档\最近的\awesome-golang\docs\code\go-super\61-main.go"
main() 开始的部分
go func() 开始的部分
func() 开始的部分
最里面go func() 开始的部分
func() 结束的部分
go func() 结束的部分
main() 结束的部分
::: warning📜 对上面的解释: return
直接跳出当前的函数, 注意这个函数也可以是当前的协程 go func()
:::
Lable跳转标签
💡简单的一个案例如下:
package main
import (
"fmt"
"time"
)
func main() {
//Go语言几种退出程序的方式
//1. os.Exit() 退出程序
//2. panic() 抛出异常
//3. return 退出函数
//4. defer + recover() 捕获异常
//5. runtime.Goexit() 退出当前协程
//6. os.Kill 杀死进程
//7. os.Interrupt 中断进程
//8. block 跳出循环
//9. continue 跳出当前循环 继续下一次循环
fmt.Println("main() 开始的部分")
go func() {
fmt.Println("go func() 开始的部分")
func() {
fmt.Println("func() 开始的部分")
go func() {
Lable1:
fmt.Println("最里面go func() 开始的部分")
//等待1s
time.Sleep(time.Second)
// 标签跳转
goto Lable1
fmt.Println("最里面go func() 结束的部分")
}()
//等待2s
time.Sleep(2 * time.Second)
fmt.Println("func() 结束的部分")
}()
fmt.Println("go func() 结束的部分")
}()
//等待5s
time.Sleep(time.Second * 5)
fmt.Println("main() 结束的部分")
}
🚀 编译结果如下:
PS D:\文档\最近的\awesome-golang\docs\code\go-super> go run .\64-main.go
main() 开始的部分
go func() 开始的部分
func() 开始的部分
最里面go func() 开始的部分
最里面go func() 开始的部分
func() 结束的部分
go func() 结束的部分
最里面go func() 开始的部分
最里面go func() 开始的部分
最里面go func() 开始的部分
main() 结束的部分