关于golang: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的透露。

因而锁的开释最好在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更多的注意事项,欢送小伙伴们在下方留言探讨呀!

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理