“This is the 22nd day of my participation in the August Gwen Challenge

error

  • Abnormal conditions that occur during program execution are called errors
  • Builtin package error interface is used as the error type in Go language. The official source code is defined as follows
    • Contains only one method, which returns a string indicating an error message
// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
type error interface {
	Error() string
}
Copy the code
  • Errors in Go are returned by methods/functions, because Go assumes that using other languages is similar to try… The catch approach affects the structure of the program
  • In the errors package of Go language standard library, the implementation structure of error interface errorString is provided, and the error () method of error interface is rewritten. Additional functions are provided to quickly create errors
package errors

// New returns an error that formats as the given text.
func New(text string) error {
	return &errorString{text}
}

// errorString is a trivial implementation of error.
type errorString struct {
	s string
}

func (e *errorString) Error(a) string {
	return e.s
}

Copy the code
  • If the error message is made up of many variables (small pieces), you can helpfmt.Errorf("verb",...)Complete error message formatting because the bottom layer is errors.new ()
// Errorf formats according to a format specifier and returns the string
// as a value that satisfies error.
func Errorf(format string, a ...interface{}) error {
	return errors.New(Sprintf(format, a...))
}
Copy the code

Custom error

  • Create an error using the Go language standard library and return
func demo(i, k int) (d int, e error) {
	if k == 0 {
		e = errors.New("Can't start with zero.")
		d=0
		return
	}
	d = i / k
	return
}

func main(a) {
	result,error:=demo(6.0)
	fmt.Println(result,error)
}
Copy the code
  • If the error message consists of multiple contents, the following implementation can be used
func demo(i, k int) (d int, e error) {
	if k == 0 {
		e = fmt.Errorf("% s and % d % d"."The divisor cannot be 0. The two arguments are :", i, k)
		d = 0
		return
	}
	d = i / k
	return
}

func main(a) {
	result, error := demo(6.0)
	fmt.Println(result, error)
}
Copy the code

Error handling in Go

  • You can ignore error messages and use placeholders
func demo(i, k int) (d int, e error) {
	if k == 0 {
		e = fmt.Errorf("% s and % d % d"."The divisor cannot be 0. The two arguments are :", i, k)
		d = 0
		return
	}
	d = i / k
	return
}

func main(a) {
	result, _ := demo(6.0)
	fmt.Println(result)
}
Copy the code
  • Use if to handle errors; in principle, every error should be resolved
func demo(i, k int) (d int, e error) {
	if k == 0 {
		e = fmt.Errorf("% s and % d % d"."The divisor cannot be 0. The two arguments are :", i, k)
		d = 0
		return
	}
	d = i / k
	return
}

func main(a) {
	result, error := demo(6.0)
	iferror ! =nil {
		fmt.Println("Error occurred", error)
		return
	}
	fmt.Println("Program executed successfully with the result :", result)
}
Copy the code

Defer to use

  • Defer can be deferred in Go, and can be deferred when the current function is finished
  • The most common thing that defer does is close the connection (database connection, files, etc.). You can open the connection and close the code after defer, and then perform other functions
    • In many languages it is required to execute sequentially, meaning that the closing code must be written last, but it is common to forget to close and run out of memory. Golang deferred solves this problem nicely. Will defer be executed last wherever it is written
func main(a) {
   fmt.Println("Open the connection")
   defer func(a){
      fmt.Println("Close connection")
   }()
   fmt.Println("Perform operations")
   // Output: open connection for operation close connection
}
Copy the code

Multiple defer

  • The multiple defer is executed in a stack structure, generated first and then executed
  • It is possible in many code structures to generate multiple objects that your program would like to close in reverse order, and multiple deferred can solve this problem
func main(a) {
   fmt.Println("Open connection A")
   defer func(a){
      fmt.Println("Close connection A")
   }()
   fmt.Println("Open connection B")
   defer func(a){
      fmt.Println("Close connection B")
   }()
   fmt.Println("Perform operations")
   // Output: Open connection A open connection B Close connection B Close connection A
}
Copy the code

Defer and return are combined

  • When defer and return coexist, the return is understood as a combination of two executions (not atomic instructions), one that assigns a value to the return value and the other that returns an escape function

  • Defer and return in the overall order of execution

    • Assign the return value first
    • Perform the defer
    • Return escape function
  • The return value receiver variable was not defined and the return value was assigned when defer was executed

func f(a) int{
	i:=0
	defer func(a){
		i=i+2} ()return i
}

func main(a) {
	fmt.Println(f())/ / output: 0
}
Copy the code
  • Declare the receive return value variable and modify the return value content when you defer.
    • The return value cannot be assigned because there is no content after the return, so the return value does have content when we defer
func f(a) (i int){
	defer func(a){
		i=i+2} ()return
}
func main(a) {
	fmt.Println(f())/ / output: 2
}
Copy the code

panic

  • Panic is a builtin function
// The panic built-in function stops normal execution of the current
// goroutine. When a function F calls panic, normal execution of F stops
// immediately. Any functions whose execution was deferred by F are run in
// the usual way, and then F returns to its caller. To the caller G, the
// invocation of F then behaves like a call to panic, terminating G's
// execution and running any deferred functions. This continues until all
// functions in the executing goroutine have stopped, in reverse order. At
// that point, the program is terminated and the error condition is reported,
// including the value of the argument to panic. This termination sequence
// is called panicking and can be controlled by the built-in function
// recover.
func panic(v interface{})
Copy the code
  • Panic is somewhat similar to throw in other programming languages, which throws exceptions. Terminates the rest of the code after panic. And print the error stack information
func main(a) {
   fmt.Println("1")
   panic("Panic did it, ha ha!")
   fmt.Println("2")}Copy the code
  • The execution result
Goroutine 1 [running]: main.main() D:/gowork/c/main.go:7 +0x80Copy the code
  • Note that Panic did not stop the program immediately (os.exit (0)) and defer still executed.
func main(a) {
   defer func(a){
      fmt.Println("Defer implementation")
   }()
   fmt.Println("1")
   panic("Panic did it, ha ha!")
   fmt.Println("2")}Copy the code

recover

  • Recover () means to recover the program from panic(), so that the program runs normally
  • Recover () is a builtin function like panic(v), which can receive panic information and restore the normal operation of the program
// The recover built-in function allows a program to manage behavior of a
// panicking goroutine. Executing a call to recover inside a deferred
// function (but not any function called by it) stops the panicking sequence
// by restoring normal execution and retrieves the error value passed to the
// call of panic. If recover is called outside the deferred function it will
// not stop a panicking sequence. In this case, or when the goroutine is not
// panicking, or if the argument supplied to panic was nil, recover returns
// nil. Thus the return value from recover reports whether the goroutine is
// panicking.
func recover(a) interface{}
Copy the code
  • Recover () is generally used inside defer. If there is no panic information, return nil. If there is panic,recover will cancel the panic state
func main(a) {
	defer func(a) {
		if error:=recover(a); error! =nil{
			fmt.Println("Panic occurred, use reover to get information :",error)
		}
	}()
	fmt.Println("11111111111")
	panic("出现panic")
	fmt.Println("22222222222")}Copy the code
  • The output
11111111111 Panic has occurred, use reover to obtain information: Panic has occurredCopy the code

Panic and recover() during function calls

  • Recover () can only restore panic() in the current function level or in the current function call function. After recovery, the current level function call ends, but the function calling this function can continue execution.
  • If there is no recover(), the program terminates. If there is no recover(), the level function of recover() means there is no panic, and panic will not be passed upward
func demo1(a){
	fmt.Println("Top half of Demo1")
	demo2()
	fmt.Println("Second half of Demo1")}func demo2(a){
	defer func(a) {
		recover(a)// Restore here
	}()
	fmt.Println("First half of Demo2")
	demo3()
	fmt.Println("Second half of Demo2")}func demo3(a){
	fmt.Println("Demo3 First Half")
	panic("Panic appears in Demo3")
	fmt.Println("Second half of Demo3")}func main(a) {
	fmt.Println("Procedure initiated")
	demo1()
	fmt.Println("End of program")}Copy the code