Golang中的错误处理的示例详解

 更新时间:2022年12月14日 09:36:25   作者:梦想画家  
这篇文章主要为大家详细介绍了Golang中的错误处理的相关资料,文章中的示例代码讲解详细,对我们学习Golang有一定帮助,需要的可以参考一下

本文介绍Golang错误处理机制,包括不同类型错误处理、定义运行时错误等内容。

golang错误处理机制

Go错误处理类似C语言,没有提供任何异常,以及类java语言使用的try/catch异常处理机制。go异常处理仅简化为预定义的Error类型,Go没有提供异常处理机制,不能抛出类似许多其他语言的异常。相反,Golang集成了新的错误处理机制,如panic 和 recovery。

error类型

error类型仅包括Error方法,返回string类型标识具体的错误信息。代码如下:

// The built-in error interface is a regular interface for handling errors. 
// where nil means no errors. 
type error interface { 
    Error() string 
}

我们看到错误处理类型实际上是一个接口,包含一个简单的error()方法,其返回值是一个字符串。通过定义可知:要实现错误处理,只需要向error()方法返回一个简单的字符串。

示例

下面先看一个错误处理示例:

func main() {
    conent, err := openFile()
    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Println(string(conent))
    }
}

只要 err!= nil (检测到存在错误), 它将从执行中终止,否则继续正常的执行流。

Go中很多函数返回多个值,通常其中一个返回值是错误类型。举例: strconv.Atoi(),转换字符串数据为数值类型,返回两个值,第一个是转换结果,第二个是错误。如果正常转换,第二个返回值为nil。反之转换失败,可从错误中获得错误原因。

下面示例检查用户输入数据是否为数值,通过示例可以学习如何处理错误:

package main
import (
    "fmt"
    "strconv"
)
func main() {
	var input string
	fmt.Print("Type some number: ")
	fmt.Scanln(&input)
	number, err := strconv.Atoi(input)
	if err == nil {
		fmt.Println(number, "is number")
	} else {
		fmt.Println(input, "is not number")
		fmt.Println(err.Error())
	}
}

如果有错误显示错误信息,反之输出结果。

创建错误对象

内置方法

除了内置函数返回错误,我们可以创建错误,主要有两种方法:

  • errors.New()
  • fmt.Errorf()

下面示例展示如何自定义错误对象。首先提供一个validate()对象,之后用于检查用户数是否为空,如果为空产生错误:

func validate(input string) (bool, error) {
	if strings.TrimSpace(input) == "" {
		return false, fmt.Errorf("%s can't be empty", input)
		//return false, errors.New("cannot be empty")
	}
	return true, nil
}
func main() {
	var name string
	fmt.Print("Type your name: \n")
	fmt.Scanln(&name)
	if valid, err := validate(name); valid {
		fmt.Println("hello", name)
	} else {
		fmt.Println(err.Error())
	}
}

第三方库

有时需要在错误对象上增加额外信息:

import "github.com/pkg/errors"
internal := errors.New("internal error")
// 给error增加其他上下文信息
wrapped := errors.Wrap(internal, "wrapper")
// 获得原始错误信息
unwrapped := errors.Cause(wrapped)

pkg/errors是内置errors的替代工具,尽管内置error也提供了类似功能:

import "errors"
internal := errors.New("internal error")
// add additional context to an error
wrapped := fmt.Errorf("wrapper: %w", internal)
// get original error
unwrapped := errors.Unwrap(wrapped)

但内置功能相对较少,建议直接使用pkg/errors.

完整示例:

import (
	"fmt"
	"github.com/pkg/errors"
	"strings"
)
func validate(input string) (bool, error) {
	if strings.TrimSpace(input) == "" {
		err := errors.New("can't be empty")
		return false, errors.Wrap(err, "input error")
	}
	return true, nil
}
func main() {
	var name string
	fmt.Print("Type your name: \n")
	fmt.Scanln(&name)
	if valid, err := validate(name); valid {
		fmt.Println("hello", name)
	} else {
		fmt.Println(errors.Unwrap(err))
	}
}

panic

panic是Go内置函数,类似其他语言的异常。当运行时出现该函数,则程序在该点终止。

声明panic

go代码中遇到panic时,不再继续执行。这种这种场景可以使用内置panic函数:

func panic( interface{} )

可以传入字符串或其他类型参数,情况示例:

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")
    }

内置操作

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)
}

上面代码因为除数为0,程序终止并报错:panic: runtime error: integer divide by zero

另外方法slice时,索引超出范围时也会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
}

那么时间使用panic函数呢?

  • 当程序不能继续执行时使用。举例,web服务器不能绑定特定端口。
  • 程序出错时使用。举例,假设方法接收指针类型参数,实际调用时传入nil。

panic与defer

还是从示例开始吧:

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

我们看到多个defer,类似栈,先进后出。panic总是让所有defer执行完毕后才抛出。

recover

前面我们看了error和panic两类异常,前者类似java中的运行时异常,后者类似于非运行时异常。error我们可以捕获或忽略,但panic要么终止运行,要么手动恢复,也就是手动处理这类错误,如给用户提示。下面同时示例来说明:

func main() {
	fmt.Println("lets learn about recover() in golang")
	Panicfunc()
	fmt.Println("learned all about recover() ")
}
func Panicfunc() {
	defer Panicrecover()
	fmt.Println("instruction just before panicking situation")
	panic("Panicfunc  resume  execution")
	fmt.Println("instruction after panic does not execute")
}
func Panicrecover() {
	if err := recover(); err != nil {
		fmt.Printf("Recovered from panic: %v \n", err)
	}
}

输出结果:

lets learn about recover() in golang
instruction just before panicking situation        
Recovered from panic: Panicfunc  resume  execution 
learned all about recover()              

我们看到panic之后代码不会执行,但recover捕获的错误处理代码能够执行。

到此这篇关于Golang中的错误处理的示例详解的文章就介绍到这了,更多相关Go错误处理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Golang CSP并发机制及使用模型

    Golang CSP并发机制及使用模型

    这篇文章主要为大家介绍了Golang CSP并发机制及使用模型,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • Go 第三方库之类型转换问题

    Go 第三方库之类型转换问题

    今天给大家介绍一个第三方库,专门处理类型转换的问题。对Go 第三方库之类型转换问题感兴趣的朋友跟随小编一起看看吧
    2021-08-08
  • 浅谈Golang 嵌套 interface 的赋值问题

    浅谈Golang 嵌套 interface 的赋值问题

    这篇文章主要介绍了浅谈Golang 嵌套 interface 的赋值问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • Sublime Text3安装Go语言相关插件gosublime时搜不到gosublime的解决方法

    Sublime Text3安装Go语言相关插件gosublime时搜不到gosublime的解决方法

    本文主要介绍了Sublime Text3安装Go语言相关插件gosublime时搜不到gosublime的解决方法,具有一定的参考价值,感兴趣的可以了解一下
    2022-01-01
  • Go语言字符串操作指南:简单易懂的实战技巧

    Go语言字符串操作指南:简单易懂的实战技巧

    本文将介绍Go语言中字符串的实战操作,通过本文的学习,读者将掌握Go语言中字符串的常用操作,为实际开发提供帮助,需要的朋友可以参考下
    2023-10-10
  • Go素数筛选分析详解

    Go素数筛选分析详解

    学习Go语言的过程中,遇到素数筛选的问题。这是一个经典的并发编程问题,是某大佬的代码,短短几行代码就实现了素数筛选,这篇文章主要介绍了Go素数筛选分析,需要的朋友可以参考下
    2022-10-10
  • Go语言接口用法实例

    Go语言接口用法实例

    这篇文章主要介绍了Go语言接口用法,实例分析了Go语言接口的功能、定义及使用技巧,需要的朋友可以参考下
    2015-02-02
  • Golang实现Redis过期时间实例探究

    Golang实现Redis过期时间实例探究

    这篇文章主要介绍了Golang实现Redis过期时间实例探究,
    2024-01-01
  • Go语言中for循环的经典案例分析

    Go语言中for循环的经典案例分析

    for循环问题,在面试中经常都会被问到,并且在实际业务项目中也经常用到for循环,要是没用好,一不下心就掉坑。本文为大家挑选了几个经典的案例,一块来探讨下,看看如何避免掉坑,多积累积累采坑经验
    2023-02-02
  • 详解Go语言中泛型的实现原理与使用

    详解Go语言中泛型的实现原理与使用

    本文是对泛型的基本思想及其在 Go 中的实现的一个比较容易理解的介绍,同时也是对围绕泛型的各种性能讨论的简单总结,感兴趣的可以学习一下
    2022-05-05

最新评论