SoFunction
Updated on 2025-03-04

Deeply explore the error strategy and exception mechanism of Go language

Preface

As developers, we cannot guarantee that the program will never have exceptions during its running process. For exceptions, in many programming languages, try-catch statements can be used to catch them. The developers of Go obviously feel that try-catch has been abused, so Go does not support using try-catch statements to catch exceptions.

So, how does Go define and handle program exceptions?

Go language divides the problems that occur when running a program into two types: errors and exceptions. Errors are one of the expected results of the running of a program (such as a function). When you call a function, you should handle the error situation. Exceptions are unpredictable (of course they can also be triggered manually) and will cause serious errors to interrupt the program.

Go Error Handling Policy

When writing a Go language program, it is generally recommended to tell the caller whether the function is successfully executed by the last return value of the function. It can be discussed in two situations:

In the first case, if the execution result of the function is only correct and failed, the return value can bebooleantype:

func exists(key string) bool {
	//to check if the key is exists
	return true
}
 
if ok := exists("test"); ok {
	// do something
}

In the second case, if you want to get the caller to get more detailed error information, it is obviously not enough to return a boolean value. At this time, you can return one.errortype,errorType is an interface, only oneErrorMethod interface:

type error interface {
	Error() string
}

passerrorType ofErrorMethods can obtain more detailed error information, which facilitates callers to handle further, so inGoIn the methods and functions of the standard library, theerrorTypes are the last return value, such as what we mentioned in our previous articlesosPackedOpenandCreatefunction:

package os
 
func Open(name string) (*File, error) {
	return OpenFile(name, O_RDONLY, 0)
}
 
func Create(name string) (*File, error) {
	return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
}

When the last return value of the functionerrorNot fornilWhen , it means that the execution is unsuccessful, and other return values ​​should be ignored at this time:

file,err := ("./")
 
if err != nil{
  	return err
}
 
defer ()

In the above code, if error is not nil, then the variable file is nil, indicating that a file handle cannot be obtained. An error is returned directly, because if you continue to execute it, the program may crash.

Of course, in all cases, when the error returned is not nil, other return values ​​must be discarded, such as when reading a file using the Read() method:

Read(p []byte) (n int, err error)

When reading the file to the endReadThe method will return aError:

var EOF = ("EOF")

AlthougherrorNot fornil, but the read byte array should still be saved instead of discarding it.

Several ways to create an error

When we develop our own functions, we can also create our own error types, and there are several ways:

errors package

errorsPackedNew()Functions can create a text messageerrortype:

package main
 
func main() {
	var s = []int{1, 2, 3}
	s[3] = 10
}

fmt package

fmtPackedErrorfFunctions can format text as error information and return an error type, so its function is similar to the function.

func getFile(name string)(*,error){
	if name == ""{
		return nil,("file name could not be empty")
	}
}

Functions can also encapsulate other functionserrorType, return a new oneerrorType to form a complete error chain:

doc, err := ()
()
if err != nil {
	return nil, ("parsing %s as HTML: %v", url,err)
}

Custom error type

In fact, the above two ways to create error types are essentially implemented.errorInterface, we can also create aErrorThe method type is implementederrorinterface:

type Result struct {
	Code    int
	Message string
	Data    interface{}
}
 
func (r Result) Error() string {
	return 
}

How to handle errors

When the call function or method returns the return value haserrorWhen it comes to types, of course, you can choose to ignore the error directly, but the more appropriate way is to deal with the corresponding errors. There are several processing strategies:

Return the error directly

For a function, if an error is encountered during execution, it can be returned directly to the upper caller:

func SendMessage(url string) error {
	if url == ""{
		return ("url can't not be empty")
	}
	_, err := (url)
	if err != nil {
		return err
	}
	return nil
}

Log and continue running

When the returned error is encountered when calling the function, if it does not affect the program's operation, you can also choose to record the error log and execute it as follows:

if err := SendMessage("https://xxx/sendMessage");err != nil{
	("the message sending been broken by : %v\n", err)
}
 

Log and end the run

If an error affects the execution of the program, you can also log the log and exit the execution of the program:

if err := SendMessage("https://xxx/sendMessage");err != nil{
	("the message sending been broken by : %v\n", err)
	(1)
}

Record the log and exit the execution, use it directlylogPackedFatalfFunctions can do it, so the simpler way of the above code is:

if err := SendMessage("https://xxx/sendMessage");err != nil{
	("the message sending been broken by : %v\n", err)
}

Go exception handling mechanism

In Go language, exceptions refer to errors that will cause a program to crash and cannot continue to run, such as array out of bounds or null pointer reference, which will triggerpanicabnormal:

package main
 
func main() {
	var s = []int{1, 2, 3}
	s[3] = 10
}

The above program runs as follows, and it can be seen that the array cross-border exception is triggered:

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

Whether in the main coroutine or the child coroutine, once triggeredpanicException, the entire program will be terminated.

panic function

In addition to unpredictable exceptions such as array cross-border, they will be automatically triggered.panic, can also be called manuallypanicThe function triggers an exception to terminate the program's run:

func loadConfig(path string){
	panic("can't load the config file on path " + path)
}

It is best not to call a good program on its own initiative.panicFunctions, especially when developing class libraries, are best to returnerrorType to tell the caller what error occurred, not triggeringpanicCauses the program to terminate operation.

Recover function

When it happenspanicWhen an exception is not caught, the program will terminate the run. In Go language, it can be used.deferStatements andrecoverFunction pattern to capturepanicabnormal:

package main
 
import (
	"fmt"
	"log"
)
 
func main() {
 
	n1 := FindElementByIndex(1)
	(n1)
  
	n2 := FindElementByIndex(4)
	(n2)
}
 
func FindElementByIndex(index int) int {
	defer func() {
		if e := recover(); e != nil {
			(e)
		}
	}()
	s := []int{1, 2, 3, 4}
	return s[index]
}
 

Summarize

This article discusses the error strategy and exception mechanism of Go language in depth. It mainly introduces the importance of error handling, as well as error types and handling functions in Go language. In addition, the exception mechanism of Go language is discussed, including the use of panic and recover functions. Through reasonable error handling and exception handling, we can improve the maintainability and reliability of our code and reduce potential bugs and failures. I hope this article is helpful to you, thanks for reading~

The above is a detailed content of in-depth exploration of Go's error strategies and exception mechanisms. For more information about Go's error strategies and exception mechanisms, please pay attention to my other related articles!