golang panic及处理机制

 

一 panic机制

  panic会将这个异常不断向上抛出,直到有地方处理它,如果有处理,则不会再向上抛出。倘若没有处理,那么最终会导致main挂掉.

 golang虽然没有try catch机制,却有一种类似的recover机制,后续demo我们可以观测到它的用法和作用

 

二 实例   

2.1 main用recover

func main() {
  defer func() {
      if err := recover(); err != nil {
          log.Println("err:", err)
      }
  }()
  go test1()
  time.Sleep(time.Second * 3)
  panic(errors.New("stop test1"))
  log.Println("123")
  select {}
}
func test1() {
  for {
      tm := time.NewTicker(time.Second)
      select {
      case <-tm.C:
          log.Println("test1")
      }
  }
}

2.2 func用recover

func main() {
  defer func() {
      if err := recover(); err != nil {
          log.Println("err:", err)
      }
  }()
  go test1()
  time.Sleep(time.Second * 3)
  makeerr()
  log.Println("123")
  select {}
}

func test1() {
  for {
      tm := time.NewTicker(time.Second)
      select {
      case <-tm.C:
          log.Println("test1")
      }
  }
}
func makeerr() {
  defer func() {
      if err := recover(); err != nil {
          log.Println("makeerr:", err)
      }
  }()
  panic(errors.New("stop"))
}

此时我们在func中用recover,那么挂掉的只是func,他不会抛到main中,所以main能继续运行,继而main开辟的go test1也能继续运行

2.3 func用recover且开创goroutine

func main() {
  defer func() {
      if err := recover(); err != nil {
          log.Println("err:", err)
      }
  }()

  time.Sleep(time.Second * 3)
  makeerr()
  log.Println("123")
  select {}
}

func test1() {
  for {
      tm := time.NewTicker(time.Second)
      select {
      case <-tm.C:
          log.Println("test1")
      }
  }
}
func makeerr() {
  defer func() {
      if err := recover(); err != nil {
          log.Println("makeerr err:", err)
      }
  }()
  go test1()
  panic(errors.New("stop test"))
}

我们发现,func虽然挂掉了,但是他开创的go没挂掉,因为即使是这个函数退出了,新开的协程是相当于基于main下的一个子程,只要main不退出,他依然会“存活”

2.4 goroutine中panic

func main() {
  defer func() {
      if err := recover(); err != nil {
          log.Println("err:", err)
      }
  }()
  go test1()
  time.Sleep(time.Second * 3)
  log.Println("123")
  select {}
}
func test1() {
  log.Println("test1 start")
  panic(errors.New("stop test1"))
  log.Println("test1 end")
}

协程中如果没recover,那么error就会抛向main,main就会挂掉,从而没有执行到后面的log打印。

---> 这种情况,main中做defer recover是没用的

2.5 func1内嵌func2中panic且func2做处理

func main() {
  test1()
  time.Sleep(time.Second * 3)
  log.Println("123")
}
func test1() {
  log.Println("test1 start")
  test2()
  log.Println("test1 end")
}
func test2() {
  defer func() {
      if err := recover(); err != nil {
          log.Println("test2 err:", err)
      }
  }()
  log.Println("test2 start")
  panic(errors.New("stop test2"))
  log.Println("test2 end")
}

2.6 func1内嵌func中panic且func1做处理

func main() {
  test1()
  time.Sleep(time.Second * 3)
  log.Println("123")
}
func test1() {
  defer func() {
      if err := recover(); err != nil {
          log.Println("test? err:", err)
      }
  }()
  log.Println("test1 start")
  test2()
  log.Println("test1 end")
}
func test2() {
  log.Println("test2 start")
  panic(errors.New("stop test2"))
  log.Println("test2 end")
}

func2异常,执行终止,向调用者func1抛出进而本身退出,func1得到异常,执行终止,本身退出时recover进行处理,从而保活了main

关于golang panic及处理机制的文章就介绍至此,更多相关golang panic内容请搜索编程宝库以前的文章,希望大家多多支持编程宝库

昨日有读者对定时器的终止有疑问,今天我们来聊一聊定时器的终止与重置吧!定时器是一种通过设置一项任务,在未来的某个时刻执行该任务的机制。定时器的种类通常只有两种,一种是只执行一次的延时模式,一种是每隔一段 ...