SoFunction
Updated on 2025-03-04

Detailed explanation of Golang's Error creation and processing

error Basic concept

type error interface{
    Error() string
}

The error type in Golang is an interface with a single method whose built-in method is to return a string describing the error. The founders of Go language feel that the exception mechanism will cause confusion in the control process and reduce the readability of the code, so expecting exceptions is predictable. Therefore, when using it, error should be returned appropriately, and the caller can know the error more clearly and then handle the exception. It also means that developers must be able to identify and predict possible errors when coding, and then process them instead of ignoring the errors.

panic and recover

But there may also be some error situations that we cannot predict. A serious program error causes panic to end the program, so it provides a recover to capture panic so that the program can be restarted when panic occurs.

defer func() {
        if r := recover(); r != nil {
            ("Restart the program:", r)
        }
}()

The recover function is best in the main function and must be used always in the defer statement. In order to ensure that it is called when panic occurs, the recover function will return nil if there is no panic.

For panic errors, error information should be fully recorded, which is conducive to troubleshooting problems. For some more important services, an alarm mechanism should be appropriately added to notify relevant teams or personnel.

Creation error

// Method 1: Use ("")func div(x, y int)(int,error){
    if y==0 {
        return 0,("The divisor %d cannot be 0",y)
    }
    return x/y, nil
}
// Method 2: Use ("")ErrDivByZero := ("The divisor cannot be 0")
return 0,ErrDivByZero
// Method 3: Use (err, "The divisor cannot be 0")return 0,(err, "The divisor cannot be 0")

In Method 1, the function allows the creation of new errors using formatted strings.

Functions allow context wrapping errors, use scenarios: When an error is encountered when a function calls another method, it may require returning an error from the function. useFunctions need to be noted: Because in addition to error information, they also have stack information attached, they cannot be used in large quantities in the program.

The above 3 types can be created easily and conveniently. Of course, custom error types are supported, and a new type that implements the error interface is created. For example:

// Method 4: Custom error typetype MathCalError struct {
    message string
}
// Implement the Error methodfunc (e *MathCalError) Error() string {
    return 
}
func div(x, y int) (int, error) {
    if y == 0 {
        return 0, &MathCalError{"The divisor cannot be 0"}
    }
    return x / y, nil
}

Handling errors

According to the scenarios encountered, there are basically five situations for error handling:

  • Ignore error: The caller feels that there is no impact on the error, so he or she can ignore it directly without receiving it.
  • Record errors and continue execution: The caller feels that the error has no effect but needs to be recorded, and can accept records
  • Passing Error: Continue passing error.
  • Error retry: A function is incorrect and needs to be retry again. If you want to try again when requesting a third-party interface timeout. Set a limit on the number of retrys to prevent infinite loops when the error persists.
  • Critical error terminating program: If some errors are expected to terminate the program, then panic directly.
// Ignore errorsresult,_ := getUser()
// Record errorresult,err := getUser();err!=nil{
    log,writerInfo("something error", ())
}
// Pass errorresult,err := getUser();err!=nil{
   return err
}
// Try again in errorretryCount := 0
 maxRetryCount := 3
for {
    result,err := getUser();
    if err!=nil{
       return err
       if retryCount >= maxRetryCount{
           return err
       } 
    }
    select {
    case <-():
     return ()
    case <-((retryCount) * ):
     retryCount++
     continue
 }
}
//Panic directly after errorif err := getUser(); err != nil {
    panic("something wrong") 
}

Solutions to use Error in the project

Solution 1: Define the ErrorMessage package

A package with all error messages can be defined in the project and then referenced directly when used.

package errorMsg
import "errors"
var UndefinedError = ("Undefined")
var InvalidateParamsError = ("Illegal Parameters")
// Used in main functionfunc getUser() error {
    return 
}

Solution 2: Customize error type

type ParamNotFound NotFound
type ValueNotFound NotFound
type NotFound struct {
	msg string
}
func (n *NotFound) Error() string {
	return 
}
// Handle different types of errors by using switch,func handleErrors(err error) {
  switch v := err.(type) {
  case ParamNotFound:
    ("ParamNotFound: %v\n", v)
  case ValueNotFound:
    ("ValueNotFound: %v\n", v)
  default:
    ("Other error: %v\n", v)
  }
}

at last

Effective error handling is crucial to building reliable services, and I personally think the best practice is a unified norm within the team. There are no best practices and solutions, only practices that suit your scenarios best.

The above is the detailed explanation of the creation and processing of Error in Golang practice. For more information about the creation and processing of Golang Error, please pay attention to my other related articles!