This is the 8th day of my participation in Gwen Challenge

Short step, no thousands of miles; Not small streams, beyond into rivers and seas. Steed leap, not ten steps, ten inferior horse riding, gongnot give up. Stop chipping halfway, deadwood can’t be broken; Constant dripping wears away the stone.

In the previous analysis of Singleflight, I saw that “the doCall method cleverly uses two defer to distinguish calling function exceptions from system exceptions”. Today, I will search for information and learn about the exception handling mechanism of Go. I only know one keyword panic in my current general impression.

Exceptions and errors

In Go, errors are considered an expected result; An exception is an unexpected result that may indicate a BUG or other uncontrollable problem in the program.

In Go, errors and anomalies are mainly expressed through error and panic [2]

For example, when querying a result from a map, success can be judged by additional Booleans as an expected result.

if v, ok := m["key"]; ok {
    return v
}
Copy the code

error

error

Error type in Go: error

type error interface {
    Error() string
}
Copy the code

The built-in Error interface allows developers to add any information they need for errors, which can be any type of implementation of the Error() method, as shown in [2][5].

The errors package in Go provides several commonly used functions, including errors.New, errors.Is, errors.As, errors.Unwrap, and the use of FMT.Errorf.

Erros. Is determines whether two errors are equal, and error.As determines whether an error Is of a specific type.

Using the instance

A function can usually return an error message on the last return value, a simple example:

package main

import (
	"errors"
	"fmt"
)

func myF(f float64) (float64, error) {
	if f < 0 {
		return 0, errors.New("Not legal input ")}/ / implementation
	return 0.0.nil
}

func main(a) {
	var m map[string]string
	m = make(map[string]string)
	m["a"] = "2"
	_, ok := m["a"]
	_, ok2 := m["b"]
	fmt.Println(ok) // true
	fmt.Println(ok2) // false

	_, e := myF(- 1)
	_, e2 := myF(2)
	fmt.Println(e) // Not legal input
	fmt.Println(e2) // <nil>
}
Copy the code

abnormal

Please defer and Panic Recover can handle exceptions.

defer

When an exception occurs in a program, such as an “unexpected” error such as an out-of-bounds access, it can cause the program to crash, requiring the developer to catch the exception and restore the program to normal flow. Catching exceptions is not the end goal. If the exception is unpredictable, the best way to deal with it is to directly output the exception information [1].

Defer is a deferred execution mechanism provided by Go, and each time it is executed, the corresponding function is pushed onto the stack. At the end of a function return or panic exception, Go in turn pulls the delayed function execution from the stack.

panic

Panic is used to actively throw exceptions that are executed by the program, terminating the code that is to be executed afterwards, and executing in reverse order the list of defer functions that panic might have.

recover

The recover keyword is used to catch exceptions and restore the program state from serious errors to normal state. It must be in the defer function to take effect.

Here is a code sample from defer+ Panic + Recover. As you can see, the output from defer was executed after manual panic, and the value of a is 0, so the name function should return an error if there is a panic statement in the function.

package main

import "fmt"

func main(a) {
	for i := 0; i < 10; i++ {
		a := my(i)
		fmt.Println(a)
	}
}

func my(i int) int {
	defer func(a) {
		if err := recover(a); err ! =nil {
			fmt.Println("Something abnormal has occurred.", err)
		}
	}()
	ifi ! =5 {
		return i
	} else {
		panic("panic")}return - 1
}

Copy the code

Code output:

An exception occurs. Panic 0, 4Copy the code

A processing extreme

Super robust code, adding the following code at the beginning of each function:

func myfunc(a) {
    defer func(a) {
       if err := recover(a); err ! =nil {
          fmt.Println(err)
      } 
    }()
    // Function implementation....
}
Copy the code

Of course, don’t do it all the time

[1] Errors and exceptions

[2] How do I handle Go error exceptions without a try-catch

[3] Some potholes of defer in Go

[4] Go – Panic and recover

[5] Part 31: Custom Error in Golang