
01介绍
在 Golang 语言中,语言引程序引发 panic 会导致程序崩溃,避免所以我们在程序开发时,语言引需要特别小心,避免避免引发 panic。语言引本文我们介绍 Golang 语言中比较容易引发 panic 的避免操作。
02指针
任意一种编程语言都会使用函数,语言引我们使用 Golang 编写函数或方法时,避免经常会用到指针类型的语言引返回值,这时如果执行调用空指针(指针未初始化或值为 nil),避免对于新手而言,语言引就很容易引发程序 panic。避免
type User struct { Name string Age int } func (u *User) GetInfo() (data *User) { data = &User{ Name: "frank",语言引 Age: 18, } return data } func main() { user := new(User) userInfo := user.GetInfo() fmt.Println(userInfo) if userInfo.Age >= 18 { fmt.Println("this is a man") } } 我们阅读上面这段代码,这是避免一段非常简单的返回值为指针类型的示例代码,读者朋友们试想一下。语言引
如果 GetInfo 方法体中的 data 的值来源于调用另外一个函数或方法,被调用的这个函数或方法返回值是 nil,而我们 main 函数中会使用返回值的 Age 字段作为判定条件,这时程序就会引发 panic,导致程序崩溃。
所以,我们在使用指针类型时,云服务器提供商要特别小心,不然我们就只能在调用函数或方法之前,使用 defer 和 recover 添加一段补偿代码,我个人感觉不是很优雅。
defer func() { if err := recover(); err != nil { fmt.Println("err = ", err) } }() 我一般是在判定指针类型的返回值时,为了避免程序引发 panic,我会加一个且(&&)的判定条件,判定返回值不是 nil,并且返回值的某个字段符合某种条件。
func main() { ... if userInfo != nil && userInfo.Age >= 18 { fmt.Println("this is a man") } } 03数组和切片
数组和切片类型,当我们越界访问时,也会引发 panic,导致程序崩溃。不过,一般 IDE 可以提示数组越界访问的错误,如果读者朋友使用的编辑器不会提示数组越界的错误,那你使用数组也要小心了。
func main() { code := []string{ "php", "golang"} fmt.Printf("len:%d cap:%d val:%s \n", len(code), cap(code), code) fmt.Println(code[2]) } 04通道
如果我们关闭未初始化的通道,重复关闭通道,向已经关闭的通道中发送数据,云服务器这三种情况也会引发 panic,导致程序崩溃。
func main() { var ch chan int // close(ch) ch = make(chan int, 1) ch <- 1 // close(ch) // close(ch) ch <- 2 } 05映射
如果我们直接操作未初始化的映射(map),也会引发 panic,导致程序崩溃。
func main() { var m map[string]int // m = make(map[string]int) m["php"] = 80 } 另外,操作映射可能会遇到的更为严重的一个问题是,同时对同一个映射并发读写,它会触发 runtime.throw,不像 panic 可以使用 recover 捕获。所以,我们在对同一个映射并发读写时,一定要使用锁。
func main() { var m map[string]int m = make(map[string]int) go func(map[string]int) { for { m["php"] = 80 } }(m) go func(map[string]int) { for { _ = m["php"] } }(m) time.Sleep(time.Second) } 输出结果:
fatal error: concurrent map read and map write goroutine 7 [running]: runtime.throw({ 0x10a7510, 0x0}) /usr/local/opt/go/libexec/src/runtime/panic.go:1198 +0x71 fp=0xc000050f28 sp=0xc000050ef8 pc=0x102fa51 06类型断言
如果类型断言使用不当,比如我们不接收布尔值的话,类型断言失败也会引发 panic,导致程序崩溃。
func main() { var name interface{ } = "frank" // a, ok := name.(int) // fmt.Println(a, ok) a := name.(int) fmt.Println(a) } 07总结
本文我们介绍 Golang 语言中容易引发 panic 的场景,尤其是空指针操作是最容易踩坑的场景,我们在程序开发中,一定要小心使用指针类型。
站群服务器