zhcn 编程语言 Golang Golang 容器 非公開: Go语言处理运行时错误

Go语言处理运行时错误

Go语言的错误处理理念和设计包括以下特点:

  • 能够产生错误的函数必须返回一个错误接口(error),如果调用成功则返回nil,否则返回错误。
  • 您应该在函数调用后检查错误,并在发生错误时执行任何必要的错误处理。

Go 语言没有像 Java 或 .NET 那样的异常处理机制。可以进行延迟、恐慌和恢复模拟,但官方并未推荐。 Go语言的设计者相信其他语言的异常机制是有效的。上面的逻辑被过度使用,需要为函数内部发生的异常付出大量的资源,同时,如果函数的使用者发现错误处理过于繁琐而忽略错误,程序就会在不经意的瞬间崩溃。

Go语言希望开发者将错误处理视为正常开发中必须实现的一个环节,从而正确处理所有可能导致错误的函数。错误的复杂性使得开发人员能够真正掌握错误处理。

net包中的示例

net.Dial() 是 Go 语言系统包 net 中的一个函数,通常用于创建套接字连接。

net.Dial 有两个返回值:Conn 和 error。该函数是阻塞的,在 Socket 操作后返回一个 Conn 连接对象和一个错误。如果发生错误,error 会告诉您错误的类型,并且 Conn 返回空。

根据Go语言的错误处理机制,Conn是一个重要的返回值,因此我们在这个函数中添加了一个类似于error的错误返回值。请参阅下面的代码。

 func Dial(network, address string) (Conn, error) {
    var d Dialer
    return d.Dial(network, address)
} 

io 包的 Writer 接口也会返回错误。这是代码:

 type Writer interface{
    Write(p []byte) (n int, err error)
} 

io 包还有一个 Closer 接口。仅返回一个错误。这是代码:

 type Closer interface {
    Close() error
} 

错误接口定义格式

error是Go系统声明的接口类型,代码为:

 type error interface {
    Error() string
} 

Error() 任何符合字符串格式的方法都可以实现错误接口。 Error()方法返回错误的详细描述,让用户通过这个字符串知道发生了什么错误。

自定义错误

在返回错误之前,您需要定义可能发生哪种错误。 Go语言使用errors包来定义错误。格式为:

 var err = errors.New("this is an error") 

由于错误字符串相对固定,因此它们通常在包范围内声明,并且应最小化,以便在使用errors.New 时直接返回。

1)错误包

在Go语言中定义New错误非常简单,代码如下:

 // エラーオブジェクトを作成する
func New(text string) error {
    return &errorString{text}
}

// エラー文字列
type errorString struct {
    s string
}

// 何が起こったかを返す
func (e *errorString) Error() string {
    return e.s
} 

代码说明如下:

  • 第二行实例化 errorString 结构并为错误描述成员分配一个值。
  • 第 7 行声明了 errorString 结构。该结构包含描述错误的成员。
  • 第 12 行实现了错误接口的 Error() 方法,并返回成员中错误的描述。

2)您在代码中使用了错误的定义

以下代码定义了一个除法函数,如果除数为 0,则该函数返回预定义的被零除错误。

 package main

import (
    "errors"
    "fmt"
)

// 除数が0のエラーを定義します
var errDivisionByZero = errors.New("division by zero")

func div(dividend、divisor int) (int、error) {

    //除数が0の場合は、そのまま返します
    if divisor == 0 {
        return 0、errDivisionByZero
    }

    //通常の計算で、空のエラーを返します
    return dividend / divisor、nil
}

func main() {

    fmt.Println(div(1、0))
} 

这是代码输出:

0 division by zero

代码解释:

  • 第 9 行,预定义的除以 0 错误。
  • 第 11 行声明了一个除法函数,输入被除数和除数,并返回商和误差。
  • 第14行,在除法的计算中,如果除数为0,计算结果会无穷大,所以为了避免这种情况,确定了除数,商为0除数为0的错误返回一个对象。
  • 第19行执行正常的除法计算,如果没有发生错误,则错误对象返回nil。
示例:在解析中使用自定义错误

error.New中定义的error字符串错误类型无法提供丰富的错误信息,因此如果需要返回错误信息,必须使用自定义结构体实现error接口。

以下代码实现了解析错误(ParseError)。该错误包含两件事:文件名和行号。解析错误结构还实现了错误接口的Error()方法。返回错误描述时,返回文件名和行号。

 package main

import(
     "fmt"
)

// 解析エラーを宣言する
type ParseError struct {
     Filename string // ファイル名
     Line int // 行番号
}

// errorインターフェイスを実装して、エラーの説明を返す
func(e *ParseError) Error() string {
     return fmt.Sprintf("%s:%d", e.Filename, e.Line)
}

// いくつかの解析エラーを作成する
func newParseError(filename string, line int) error {
     return &ParseError{filename, line}
}

func main() {

     var e error
     // ファイル名と行数を含むエラーインスタンスを作成する
     e = newParseError("main.go", 1)

     //エラーの説明をerrorインターフェイスで確認する
     fmt.Println(e.Error())

     //エラーインターフェイスの具体的なタイプに基づいて、詳細なエラー情報を取得する
     スイッチdetail := e.(タイプ) {
    case *ParseError: //これはjson解析エラーです。
        fmt.Printf("Filename: %s Line: %d\n", detail.Filename, detail.Line)
    default: // 他の種類のエラー
        fmt.Println("other error")
     }
} 

这是代码输出:

main.go:1
Filename: main.go Line: 1

代码说明如下:

  • 第8行声明了解析错误结构体,其中包含两个成员:文件名和行号。
  • 第 14 行实现错误接口并以字符串形式返回成员的文件名和行号。
  • 第 19 行根据指定的文件名和行号创建一个错误实例。
  • 第 25 行声明错误接口类型。
  • 在第 27 行创建了一个实例,其内部错误接口类型为 *ParserError,文件名为 main.go,行号为 1。
  • 第 30 行调用 Error() 方法,第 15 行返回错误详细信息。
  • 第 33 行通过错误断言检索详细的错误类型。
  • 解析第34行的错误类型,发现错误类型为*ParserError,此时可以获得详细的错误信息。
  • 如果不是可以处理的错误类型,第 36 行会打印另一个错误以供进一步处理。

错误对象必须实现错误接口的Error()方法。这样你就可以将所有错误写入字符串中。如果您想了解有关错误的更多信息,可以使用类型断言将错误对象转换为:获取特定错误类型的错误详细信息。

《Go语言处理运行时错误》浅显易懂的讲解!您必须观看的 2 个最佳视频

Go言語とは?|プログラミング言語のGo言語について3分でわかりやすく解説します【プログラミング初心者向け】
https://www.youtube.com/watch?v=3zfzBuDl6M4&pp=ygU9IEdvIOiogOiqnuOBr-ODqeODs-OCv-OCpOODoOOCqOODqeODvOOCkuWHpueQhuOBl-OBvuOBmSZobD1KQQ%3D%3D
【Go言語】3つの弱点を知っておこう!
https://www.youtube.com/watch?v=mY1PuRjytPo&pp=ygU9IEdvIOiogOiqnuOBr-ODqeODs-OCv-OCpOODoOOCqOODqeODvOOCkuWHpueQhuOBl-OBvuOBmSZobD1KQQ%3D%3D
Go语言的错误处理理念和设计包括以下特点:

  • 能够产生错误的函数必须返回一个错误接口(error),如果调用成功则返回nil,否则返回错误。
  • 您应该在函数调用后检查错误,并在发生错误时执行任何必要的错误处理。

Go 语言没有像 Java 或 .NET 那样的异常处理机制。可以进行延迟、恐慌和恢复模拟,但官方并未推荐。 Go语言的设计者相信其他语言的异常机制是有效的。上面的逻辑被过度使用,需要为函数内部发生的异常付出大量的资源,同时,如果函数的使用者发现错误处理过于繁琐而忽略错误,程序就会在不经意的瞬间崩溃。

Go语言希望开发者将错误处理视为正常开发中必须实现的一个环节,从而正确处理所有可能导致错误的函数。错误的复杂性使得开发人员能够真正掌握错误处理。

net包中的示例

net.Dial() 是 Go 语言系统包 net 中的一个函数,通常用于创建套接字连接。

net.Dial 有两个返回值:Conn 和 error。该函数是阻塞的,在 Socket 操作后返回一个 Conn 连接对象和一个错误。如果发生错误,error 会告诉您错误的类型,并且 Conn 返回空。

根据Go语言的错误处理机制,Conn是一个重要的返回值,因此我们在这个函数中添加了一个类似于error的错误返回值。请参阅下面的代码。

 func Dial(network, address string) (Conn, error) {
    var d Dialer
    return d.Dial(network, address)
} 

io 包的 Writer 接口也会返回错误。这是代码:

 type Writer interface{
    Write(p []byte) (n int, err error)
} 

io 包还有一个 Closer 接口。仅返回一个错误。这是代码:

 type Closer interface {
    Close() error
} 

错误接口定义格式

error是Go系统声明的接口类型,代码为:

 type error interface {
    Error() string
} 

Error() 任何符合字符串格式的方法都可以实现错误接口。 Error()方法返回错误的详细描述,让用户通过这个字符串知道发生了什么错误。

自定义错误

在返回错误之前,您需要定义可能发生哪种错误。 Go语言使用errors包来定义错误。格式为:

 var err = errors.New("this is an error") 

由于错误字符串相对固定,因此它们通常在包范围内声明,并且应最小化,以便在使用errors.New 时直接返回。

1)错误包

在Go语言中定义New错误非常简单,代码如下:

 // エラーオブジェクトを作成する
func New(text string) error {
    return &errorString{text}
}

// エラー文字列
type errorString struct {
    s string
}

// 何が起こったかを返す
func (e *errorString) Error() string {
    return e.s
} 

代码说明如下:

  • 第二行实例化 errorString 结构并为错误描述成员分配一个值。
  • 第 7 行声明了 errorString 结构。该结构包含描述错误的成员。
  • 第 12 行实现了错误接口的 Error() 方法,并返回成员中错误的描述。

2)您在代码中使用了错误的定义

以下代码定义了一个除法函数,如果除数为 0,则该函数返回预定义的被零除错误。

 package main

import (
    "errors"
    "fmt"
)

// 除数が0のエラーを定義します
var errDivisionByZero = errors.New("division by zero")

func div(dividend、divisor int) (int、error) {

    //除数が0の場合は、そのまま返します
    if divisor == 0 {
        return 0、errDivisionByZero
    }

    //通常の計算で、空のエラーを返します
    return dividend / divisor、nil
}

func main() {

    fmt.Println(div(1、0))
} 

这是代码输出:

0 division by zero

代码解释:

  • 第 9 行,预定义的除以 0 错误。
  • 第 11 行声明了一个除法函数,输入被除数和除数,并返回商和误差。
  • 第14行,在除法的计算中,如果除数为0,计算结果会无穷大,所以为了避免这种情况,确定了除数,商为0除数为0的错误返回一个对象。
  • 第19行执行正常的除法计算,如果没有发生错误,则错误对象返回nil。
示例:在解析中使用自定义错误

error.New中定义的error字符串错误类型无法提供丰富的错误信息,因此如果需要返回错误信息,必须使用自定义结构体实现error接口。

以下代码实现了解析错误(ParseError)。该错误包含两件事:文件名和行号。解析错误结构还实现了错误接口的Error()方法。返回错误描述时,返回文件名和行号。

 package main

import(
     "fmt"
)

// 解析エラーを宣言する
type ParseError struct {
     Filename string // ファイル名
     Line int // 行番号
}

// errorインターフェイスを実装して、エラーの説明を返す
func(e *ParseError) Error() string {
     return fmt.Sprintf("%s:%d", e.Filename, e.Line)
}

// いくつかの解析エラーを作成する
func newParseError(filename string, line int) error {
     return &ParseError{filename, line}
}

func main() {

     var e error
     // ファイル名と行数を含むエラーインスタンスを作成する
     e = newParseError("main.go", 1)

     //エラーの説明をerrorインターフェイスで確認する
     fmt.Println(e.Error())

     //エラーインターフェイスの具体的なタイプに基づいて、詳細なエラー情報を取得する
     スイッチdetail := e.(タイプ) {
    case *ParseError: //これはjson解析エラーです。
        fmt.Printf("Filename: %s Line: %d\n", detail.Filename, detail.Line)
    default: // 他の種類のエラー
        fmt.Println("other error")
     }
} 

这是代码输出:

main.go:1
Filename: main.go Line: 1

代码说明如下:

  • 第8行声明了解析错误结构体,其中包含两个成员:文件名和行号。
  • 第 14 行实现错误接口并以字符串形式返回成员的文件名和行号。
  • 第 19 行根据指定的文件名和行号创建一个错误实例。
  • 第 25 行声明错误接口类型。
  • 在第 27 行创建了一个实例,其内部错误接口类型为 *ParserError,文件名为 main.go,行号为 1。
  • 第 30 行调用 Error() 方法,第 15 行返回错误详细信息。
  • 第 33 行通过错误断言检索详细的错误类型。
  • 解析第34行的错误类型,发现错误类型为*ParserError,此时可以获得详细的错误信息。
  • 如果不是可以处理的错误类型,第 36 行会打印另一个错误以供进一步处理。

错误对象必须实现错误接口的Error()方法。这样你就可以将所有错误写入字符串中。如果您想了解有关错误的更多信息,可以使用类型断言将错误对象转换为:获取特定错误类型的错误详细信息。

《Go语言处理运行时错误》浅显易懂的讲解!您必须观看的 2 个最佳视频

Go言語とは?|プログラミング言語のGo言語について3分でわかりやすく解説します【プログラミング初心者向け】
https://www.youtube.com/watch?v=3zfzBuDl6M4&pp=ygU9IEdvIOiogOiqnuOBr-ODqeODs-OCv-OCpOODoOOCqOODqeODvOOCkuWHpueQhuOBl-OBvuOBmSZobD1KQQ%3D%3D
【Go言語】3つの弱点を知っておこう!
https://www.youtube.com/watch?v=mY1PuRjytPo&pp=ygU9IEdvIOiogOiqnuOBr-ODqeODs-OCv-OCpOODoOOCqOODqeODvOOCkuWHpueQhuOBl-OBvuOBmSZobD1KQQ%3D%3D