美文网首页
Go 异常处理

Go 异常处理

作者: 泥人冷风 | 来源:发表于2020-12-22 10:30 被阅读0次

1 error

Go语言内置了一个简单的错误接口作为一种错误处理机制,接口定义如下:

type error interface {
      Error() string
}

它包含一个Error()方法,返回值为string
Go的error构造有两种方式,分别是

第一种:errors.New()

package main

import (
    "errors"
    "fmt"
)

func main() {
    err := errors.New("This is an error")
    if err != nil {
        fmt.Print(err)
    }
}

执行结果

API server listening at: 127.0.0.1:23464
This is an error
Process exiting with code: 0

第二种:fmt.Errorf()

package main

import (
    "fmt"
)

func main() {
    err := fmt.Errorf("This is an error")
    if err != nil {
        fmt.Print(err)
    }
}

执行结果

API server listening at: 127.0.0.1:26641
This is an error
Process exiting with code: 0

除了直接使用Go自带的方法,还可以自定义错误。下面以自然数函数作为例子:

package main

import "fmt"

type NotNature float64

func (err NotNature) Error() string {
    return fmt.Sprintf("自然数为大于或等于0的数: %v", float64(err))
}

/*
* 自然数处理
 */
func Nature(x float64) (float64, error) {
    if x < 0 {
        return 0, NotNature(x)
    } else {
        return x, nil
    }
}

func main() {
    fmt.Println(Nature(1))
    fmt.Println(Nature(-1))
}

执行结果

API server listening at: 127.0.0.1:9994
1 <nil>
0 自然数为大于或等于0的数: -1
Process exiting with code: 0

需要注意一下几点:

    1. 如果函数需要处理异常,通常将error作为多值返回的最后一个值,返回的error值为nil则表示无异常,非nil则是有异常。
    1. 一般先用if语句处理error!=nil,正常逻辑放if后面。

Go语言的error代表的并不是真“异常”,只是通过返回error来表示错误信息,换句话说,不是运行时错误范围预定义的错误,某种不符合期望的行为并不会导致程序无法运行(自然数函数例子),都应使用error进行异常处理。当程序出现重大错误,如数组越界才会将其当成真正的异常,并用panic来处理。

2 panic

Go不使用try...catch方法来处理异常,而是使用panic和recover

package main

import (
    "errors"
    "fmt"
)

func main() {
    fmt.Println("Hello,Go!")
    panic(errors.New(" i am a error"))
    fmt.Println("hello,again!")
}

执行结果

API server listening at: 127.0.0.1:34729

Hello,Go!

panic: i am a error goroutine 1 [running]: main.main() c:/Users/learn/go/GoHello/main.go:10 +0x107

Process exiting with code: 0

从上述代码可以看出,panic后面的程序不会被执行了。但是我们捕捉异常并不是为了停止程序(一般情况),而是为了让程序能正常运行下去,这时候就到recover出场了。

package main

import "fmt"

func main() {
    defer func() {
        fmt.Println("我是defer里面第一个打印函数")
        if err := recover(); err != nil {
            fmt.Println(err)
        }
        fmt.Println("我是defer里面第二个打印函数")
    }()
    f()
}

func f() {
    fmt.Println("1")
    panic("我是panic")
    fmt.Println("2")
}

执行结果

API server listening at: 127.0.0.1:47248
1
我是defer里面第一个打印函数
我是panic
我是defer里面第二个打印函数
Process exiting with code: 0

可以看到,f函数一开始正常打印,当遇到panic,就跳到defer函数,执行defer函数里的内容

需要注意的是,defer函数里打印的err其实就是panic里面的内容。

下面详细介绍一下panic和recover的原理。首先来看一下panic和recover的官方定义

func panic(v interface{})
内置函数panic会停止当前goroutine的正常执行。当函数F调用panic时,F的正常执行立即停止。任何被F延迟执行的函数都将以正常的方式运行,然后F返回其调用者。对调用方G来说,对F的调用就像调用panic一样,终止G的执行并运行任何延迟的函数。直到执行goroutine中的所有函数都按逆序停止。此时,程序将以非0退出代码终止。此终止序列称为panicking,可由内置函数recover控制。

func recover() interface{}
recover内置函数允许程序管理panicking的goroutine的行为。在defer函数(但不是它调用的任何函数)内执行恢复调用,通过恢复正常执行来停止panicking序列,并检索传递给panic调用的错误值。如果在defer函数之外调用recover,则不会停止panicking的序列。在这种情况下,或者当goroutine不panicking时,或者提供给panic的参数是nil,recover返回nil。因此,recover的返回值报告goroutine是否panicking

ps:defer和recover必须在panic之前定义,否则无效。

3 源码分析

errors.New的定义如下

// src/errors/errors.go

// New returns an error that formats as the given text.
// Each call to New returns a distinct error value even if the text is identical.
func New(text string) error {
    return &errorString{text}
}

// errorString is a trivial implementation of error.
type errorString struct {
    s string
}

func (e *errorString) Error() string {
    return e.s
}
    1. New函数返回格式为给定文本的错误
    1. 即使文本是相同的,每次对New的调用都会返回一个不同的错误值。

相关文章

  • 异常处理

    Go 的异常处理不同于其他语言使用的结构 对于 go 的异常处理, 使用 defer, panic, recove...

  • go 异常处理

    error 是一个接口,接口中有Error()方法和返回值string // 就相当于 var tmp error...

  • Go异常处理

    想法 Go的异常处理是比较特别的.有人不喜欢这种走两步就 if err,然而生活就是这样. 这是我理解的实现方式之...

  • go 异常处理

    error 接口声明如下: 创建error err:=errors.New("")//返回的是其返回的error类...

  • Go 异常处理

    1 error Go语言内置了一个简单的错误接口作为一种错误处理机制,接口定义如下: 它包含一个Error()方法...

  • Go 异常处理

    目录 panic和recover 作用 panic 能够改变程序的控制流,调用 panic 后会立刻停止执行当前函...

  • 异常处理

    异常处理 Go语言追求简洁优雅,所以,Go语言不支持传统的 try…catch…finally 这种异常,因为Go...

  • Golang 学习笔记八 错误异常

    一、错误异常 《快学 Go 语言》第 10 课 —— 错误与异常Go 语言的异常处理语法绝对是独树一帜,在我见过的...

  • golang的异常处理

    go语言是不支持异常的,go语言的设计者认为异常会被不成熟的程序员滥用,导致异常的处理过去复杂;go语言取消异常的...

  • (译)Go 语言中异常处理的艺术

    原文链接:The Art of Error Handling in Go Go 语言的异常处理与其他语言截然不同,...

网友评论

      本文标题:Go 异常处理

      本文链接:https://www.haomeiwen.com/subject/qbbrnktx.html