阅读 155

Golang中关于Panic的俩个易错点

在日常开发中一不小心程序就会出现panic,如果没有注册recoverpanic会直接中断程序后面的逻辑,使用不当会带来巨大的隐患。下面小老虎就来介绍俩点关于panic的常见错误!

一、Panic与Recover

在并发问题中,我们常常使用读写锁来保证并发的安全性。在内存泄漏的七种场景中我们提到锁的使用不当,会使得groutine因获取不到锁,而导致内存泄漏。下面以超超和婷婷获取电视使用权为例。

定义电视结构体并提供注册和获取当前使用者的方法

type Television struct {
  belong string
  sync.RWMutex
}

func (m *Television) set(name string) {
  m.Lock()
  m.belong = name
  m.Unlock()
}

func (m *Television) get() string {
  m.RLock()
  user := m.belong
  m.RUnlock()
  return user
}复制代码

主进程中用户并发获取电视机使用权

func main() {
  users := []string{"chaochao", "tingting"}
  tv := &Television{}
  w := sync.WaitGroup{}
  usersLen := len(users)

  w.Add(usersLen)
  for i := 0; i < usersLen; i++ {
    go func(user string) {
      tv.set(user)
      w.Done()
    }(users[i])
  }
  w.Wait()
  fmt.Println("TV user is", tv.get())
}复制代码

输出结果

TV user is tingting复制代码

看似没有任何问题,如果get方法和set方法再复杂一些,中间不小心出了panic,会怎么样呢?

func (m *Television) set(name string) {
  m.Lock()
  m.belong = name
  //模拟出现的panic
  panic("setErr")
  m.Unlock()
}复制代码

那么整个程序都会崩溃,线上如果出现这样的问题,基本属于中大奖了!因此需要注册一个deferrecover这个panic,使得程序能够继续运行。

func main() {
  users := []string{"chaochao", "tingting"}
  tv := &Television{}
  w := sync.WaitGroup{}
  usersLen := len(users)

  w.Add(usersLen)
  for i := 0; i < usersLen; i++ {
    go func(user string) {
      //获取处理异常
      defer func() {
        if err := recover(); err != nil {
          fmt.Println("err:", err)
        }
      }()
      tv.set(user)
      w.Done()
    }(users[i])
  }
  w.Wait()
  fmt.Println("TV user is", tv.get())
}复制代码

看似程序到这没有问题了,但是真是如此吗?

二、内存泄漏

set方法中,panic之前有一个获取锁的操作,panic之后set方法直接退出了,并没有释放锁。这时其他协程在尝试获取锁时就会失败,从而造成Goroutine的泄漏。

image-20220226153642102因此锁的释放最好在lock后注册一个defer进行释放。

type Television struct {
  belong string
  sync.RWMutex
}

func (m *Television) set(name string) {
  m.Lock()
  defer m.Unlock()
  m.belong = name
}

func (m *Television) get() string {
  m.RLock()
  defer m.RUnlock()
  user := m.belong
  return user
}复制代码
三、总结

本文介绍了panicrecover的使用场景,recover通常放在defer中防止panic中断程序给线上带来巨大的影响。紧接着介绍了锁的释放最好也放在defer中,防止painic时未释放锁导致其他协程未拿到锁而导致内存泄漏。关于painic更多的注意事项,欢迎小伙伴们在下方留言讨论呀!


作者:上山打老虎_
链接:https://juejin.cn/post/7068930735536603144


文章分类
代码人生
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐