9.7Go之函数之处理RuntimeError

Go的错误处理思想以及设计

  • 一个可能造成错误的函数,需要返回值中返回一个错误接口(error),如果调用是成功的,错误接口将返回 nil,否则返回错误--->Go语言中函数的调用一定会返回调用结果err

  • 在函数调用后需要检查错误,如果发生错误,则进行必要的错误处理

Go的异常处理机制和其他语言异常处理机制比较

java等语言异常处理机制:

try{
   
}catch{
   
}finally{
   
}

Go语言可以使用defer、panic、recover模拟try...catch...finally操作。但是官方不主张这样做

Go语言中错误接口的定义格式

error 是 Go 系统声明的接口类型。位于build包下--->Error()方法返回错误的具体描述

type error interface{
   Error() string
}
/*
符合Error() string格式的方法都能实现错误接口。
Error()方法返回错误的具体描述
*/

net包和io包error处理例子

net.Dial()实例:

func Dial(network, address string) (Conn, error) {
var d Dialer
return d.Dial(network, address)
}
/*
dial.go源码包下的函数
*/

io包下writter接口实例:

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

自定义一个错误

使用 errors 包进行错误的定义

var err = errors.New("this is an error")
/*
错误字符串由于相对固定,一般在包作用域声明,应尽量减少在使用时直接使用 errors.New 返回--->直接使用.New方法返回
*/

errors包对New的定义:

// 创建错误对象
func New(text string) error {
   return &errorString{text}
}
/*
将 errorString 结构体实例化,并赋值错误描述的成员
*/

// 错误字符串
type errorString struct {
   s string
}
/*
声明 errorString 结构体,拥有一个成员,描述错误内容
*/

// 返回发生何种错误
func (e *errorString) Error() string {
   return e.s
}
/*
实现 error 接口的 Error() 方法,该方法返回成员中的错误描述
形参是指针e指向结构体errorString。通过这个方式实现接口Error()
*/

示例代码:

package main

import (
"errors"
"fmt"
)

//自定义一个错误
var errorZero = errors.New("division by zero")

/*
定义一个除法函数,被除数除以除数。如果商为0返回错误
*/
func div(dividend, divisor int) (int, error) {
//判断除数为0抛出异常
if divisor == 0 {
return 0, errorZero
}

//正常计算,返回空值
return dividend/divisor, nil //正常计算返回空的error
   /*
   进行正常的除法计算,没有发生错误时,错误对象返回 nil
   */
}

func main() {
fmt.Println(div(1,0))
}
在解析中使用自定义错误

示例代码:

package main

import "fmt"

/*
声明一个结构体,包含错误的解析
*/
type ParseError struct {
Filename string //文件名
Line int //行号
/*
声明了一个解析错误的结构体,解析错误包含有 2 个成员,分别是文件名和行号
*/
}

/*
声明一个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)
/*
创建一个实例,这个错误接口内部是 *ParserError 类型,携带有文件名 main.go 和行号 1
*/

//通过error接口查看错误描述
fmt.Println(e.Error())

//通过断言获取详细的错误信息
switch detail := e.(type) {
case *ParseError: //解析错误
fmt.Printf("Filename: %s Line: %d\n", detail.Filename, detail.Line)
default:
//其他类型的错误
fmt.Println("other error")
}
}
/*
错误对象都要实现 error 接口的 Error() 方法
所有的错误都可以获得字符串的描述
想进一步知道错误的详细信息,可以通过类型断言,将错误对象转为具体的错误类型进行错误详细信息的获取。
*/

 

 

It's a lonely road!!!