文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Golang 语言怎么避免引发 Panic?

2024-12-02 13:59

关注

02指针

任意一种编程语言都会使用函数,我们使用 Golang 编写函数或方法时,经常会用到指针类型的返回值,这时如果执行调用空指针(指针未初始化或值为 nil),对于新手而言,就很容易引发程序 panic。

  1. type User struct { 
  2.  Name string 
  3.  Age  int 
  4.  
  5. func (u *User) GetInfo() (data *User) { 
  6.  data = &User
  7.   Name"frank"
  8.   Age:  18, 
  9.  } 
  10.  return data 
  11.  
  12. func main() { 
  13.  user := new(User
  14.  userInfo := user.GetInfo() 
  15.  fmt.Println(userInfo) 
  16.  if userInfo.Age >= 18 { 
  17.   fmt.Println("this is a man"
  18.  } 

我们阅读上面这段代码,这是一段非常简单的返回值为指针类型的示例代码,读者朋友们试想一下。

如果 GetInfo 方法体中的 data 的值来源于调用另外一个函数或方法,被调用的这个函数或方法返回值是 nil,而我们 main 函数中会使用返回值的 Age 字段作为判定条件,这时程序就会引发 panic,导致程序崩溃。

所以,我们在使用指针类型时,要特别小心,不然我们就只能在调用函数或方法之前,使用 defer 和 recover 添加一段补偿代码,我个人感觉不是很优雅。

  1. defer func() { 
  2.   if err := recover(); err != nil { 
  3.    fmt.Println("err = ", err) 
  4.   } 
  5.  }() 

我一般是在判定指针类型的返回值时,为了避免程序引发 panic,我会加一个且(&&)的判定条件,判定返回值不是 nil,并且返回值的某个字段符合某种条件。

  1. func main() { 
  2.  ... 
  3.    
  4.  if userInfo != nil && userInfo.Age >= 18 { 
  5.   fmt.Println("this is a man"
  6.  } 

03数组和切片

数组和切片类型,当我们越界访问时,也会引发 panic,导致程序崩溃。不过,一般 IDE 可以提示数组越界访问的错误,如果读者朋友使用的编辑器不会提示数组越界的错误,那你使用数组也要小心了。

  1. func main() { 
  2.  code := []string{"php""golang"
  3.  fmt.Printf("len:%d cap:%d val:%s \n", len(code), cap(code), code) 
  4.  fmt.Println(code[2]) 

04通道

如果我们关闭未初始化的通道,重复关闭通道,向已经关闭的通道中发送数据,这三种情况也会引发 panic,导致程序崩溃。

  1. func main() { 
  2.  var ch chan int 
  3.  // close(ch) 
  4.  ch = make(chan int, 1) 
  5.  ch <- 1 
  6.  // close(ch) 
  7.  // close(ch) 
  8.  ch <- 2 

05映射

如果我们直接操作未初始化的映射(map),也会引发 panic,导致程序崩溃。

  1. func main() { 
  2.  var m map[string]int 
  3.  // m = make(map[string]int
  4.  m["php"] = 80 

另外,操作映射可能会遇到的更为严重的一个问题是,同时对同一个映射并发读写,它会触发 runtime.throw,不像 panic 可以使用 recover 捕获。所以,我们在对同一个映射并发读写时,一定要使用锁。

  1. func main() { 
  2.  var m map[string]int 
  3.  m = make(map[string]int
  4.  go func(map[string]int) { 
  5.   for { 
  6.    m["php"] = 80 
  7.   } 
  8.  }(m) 
  9.  
  10.  go func(map[string]int) { 
  11.   for { 
  12.    _ = m["php"
  13.   } 
  14.  }(m) 
  15.  
  16.  time.Sleep(time.Second

输出结果:

  1. fatal error: concurrent map read and map write 
  2.  
  3. goroutine 7 [running]: 
  4. runtime.throw({0x10a7510, 0x0}) 
  5.         /usr/local/opt/go/libexec/src/runtime/panic.go:1198 +0x71 fp=0xc000050f28 sp=0xc000050ef8 pc=0x102fa51 

06类型断言

如果类型断言使用不当,比如我们不接收布尔值的话,类型断言失败也会引发 panic,导致程序崩溃。

  1. func main() { 
  2.  var name interface{} = "frank" 
  3.  // a, ok := name.(int
  4.  // fmt.Println(a, ok) 
  5.  a := name.(int
  6.  fmt.Println(a) 

07总结

 

本文我们介绍 Golang 语言中容易引发 panic 的场景,尤其是空指针操作是最容易踩坑的场景,我们在程序开发中,一定要小心使用指针类型。

 

来源:Golang语言开发栈内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯