Golang中的Panic


2022年1月23日, Learn eTutorial
2145

在本教程中,您将学习 Go 编程语言中的 panic、它的重要性、如何在 Golang 中声明它、Golang 中 panic 的用途等。

Golang 中的 Panic 是什么?

在 Go 语言中,不像其他语言那样有异常。例如,如果您尝试打开一个文件而该文件不存在,Golang 将返回一些错误值而不是异常,因为 Golang 中不考虑异常。
在 Go 编程语言中,您可以使用“panic”来代替“exception”这个词。程序或应用程序继续运行或执行,但它处于一种称为“panic”的情况,因为程序在这种情况下不知道该怎么做。
异常是许多其他程序(如 Java、c#、c++)在执行期间影响指令正常流动的任何意外事件。在 Golang 中,异常一词被 panic 一词取代。

GO : Panic

Golang 中 Panic 的定义

  • panic 函数可以定义为 Golang 中的异常,它是 Golang 包下的一个内置函数。
  • 当 Go 程序在运行时发现 panic 函数时,编译器会从该点终止其执行。
  • 控制流终止并从 panic 函数开始恐慌。

Panic 示例

让我们考虑一个例子


package main
import (
 "fmt"
)

func main() {
    a,b := 1,0   // variable a & b are declared and initialized
    result := a/b        // division operation
    fmt.Println(result)
    }

输出


panic: runtime error: integer divide by zero

goroutine 1 [running]:
main.main()
 /home/gqcsh6/prog.go:11 +0x11

考虑上面的代码,它声明了变量 a 和 b,并用值 1 和 0 初始化。a = 1 和 b = 0。除法运算在变量 a 和 b 之间执行,并将最终值存储在另一个声明的变量 result 中。

GO : Panic

我们知道该操作是无效类型,并将显示错误。当我们在运行时运行代码时,它本身就会生成一个 panic。运行时错误打印为整数除以零。此外,还提到了堆栈跟踪以表示错误发生的位置,例如

main.main()

    /home/gqcsh6/prog.go:11 +0x11

为了避免这些情况,可以在 Golang 中使用内置的 panic 函数。

如何在 Golang 中声明 panic?

在 Go 语言中,当程序进入无法继续执行的情况时,程序员可以编写 panic 代码。在这种情况下,可以使用内置的 panic 函数。

语法


func panic( interface{} )

  • 当程序终止时,传递给 panic 函数的字符串或参数将显示。
GO : Panic

让我们看看如何在 Go 程序中添加 panic


package main
import  "fmt"
func main() {
 
    fmt.Println("start Go program")
    panic(" built in panic keyword gives error msg")  // panic keyword
    fmt.Println("End Go program")
    }

输出


panic:  built in panic keyword gives error msg

goroutine 1 [running]:
main.main()
 /home/vSbday/prog.go:6 +0x95

在上面的输出中,您可以看到打印出的错误消息与我们在声明 panic 关键字时传递的精确消息或字符串相同。

何时在 Golang 中使用 panic?

  • panic 函数仅应在程序无法继续执行时使用。例如:当 Web 服务器无法绑定到端口时,使用 panic 函数,因为没有其他办法。
  • 在程序员错误的情况下使用 panic。

示例:假设一个接受指针作为参数的方法在使用 nil 参数调用时,属于程序员错误,因此最好使用 panic 函数。

defer 如何与 Golang 中的函数 panic 配合使用?

在我们之前的教程中,我们已经讨论过 Golang 中的 defer。
Go 编程语言中的 defer 语句会延迟使用 defer 关键字定义的语句、函数或方法的执行。(请参阅 defer 教程以更好地理解)。defer 语句是函数内部所有执行完毕后最后打印的语句,它在方法终止之前打印。

panic 函数将停止执行,直到遇到 panic 函数之前的最后一个语句或函数,并返回错误消息。

让我们考虑下面的例子


package main
import "fmt"

func Name(firstName *string, lastName *string) {
 defer fmt.Println("Name function deferred call")
 if firstName == nil {
  panic("runtime error: first name cannot be nil")
 }
 if lastName == nil {
  panic("runtime error: last name cannot be nil")
 }
 fmt.Printf("%s %s\n", *firstName, *lastName)
 fmt.Println("return from Name")
}
func main() {
 defer fmt.Println("main() deffered call")
 firstName := "Elon"
 Name(&firstName, nil)
 fmt.Println("return from main")
}

输出


Name function deferred call
main() deffered call
panic: runtime error: last name cannot be nil

goroutine 1 [running]:
main.Name(0x7f66dc945108, 0x60)
 /tmp/sandbox2801026756/prog.go:13 +0x197
main.main()
 /tmp/sandbox2801026756/prog.go:22 +0x8c
Program exited.

现在让我们理解源代码以清楚地了解 defer 和 panic 的工作原理。
执行从 main 函数开始,其中它被定义为一个带有延迟的打印语句。main 函数只是延迟或省略其当前执行一段时间,然后移动到 main 函数中的下一条指令。

GO : Panic

控制权转到函数 Name,并打印其中的延迟函数,然后是 main 中延迟的延迟函数。

GO : Panic

控制权现在到达程序的顶层函数,打印 panic 消息,然后是堆栈跟踪,然后终止,如上面的输出所示。

GO : Panic

panic 如何与 Golang 中的切片配合使用?

让我们通过一个例子来理解。考虑下面使用切片的程序。


package main
import "fmt"

func main() {
    names := []string{  //slice data type
        "Learn eTutorials",     // index 0
        "Golang",  //index 1
        "panic tutorial", //index 2
    }    
    fmt.Println(names[0])
    fmt.Println(names[2])
}

输出


Learn eTutorials
panic tutorial

要更好地理解上述代码,请参阅我们讨论过的切片教程。
现在让我们来看看 panic 在同一个程序中是如何发生的。
我们知道在切片中,索引从数字 0 开始。当请求打印超出边界的索引时,Golang 中的 panic 函数会在运行时引发该异常或错误。
让我们看看相同的例子


package main
import "fmt"

func main() {
    names := []string{  //slice data type
        "Learn eTutorials",     // index 0
        "Golang",  //index 1
        "panic tutorial", //index 2
    }
    
    //fmt.Println(names[0]) commented
    //fmt.Println(names[2]) commented
    
    fmt.Println(names[4])
}

输出


panic: runtime error: index out of range [4] with length 3

goroutine 1 [running]:
main.main()
 /home/2x9Qrt/prog.go:15 +0x1d
GO : Panic

从输出中可以清楚地看到,程序员要求打印的切片索引范围超出索引,因为只存在索引到 2。
name[0] := Learn eTutorials
name[1] := Golang
name[2] := panic 教程

GO : Panic