Hello everyone, my name is Xie Wei, I am a programmer.

In the near future, I will continue to update the study notes of the built-in library, mainly referring to the document GOdoc and the source code of the built-in library

The topic of this section is error

Error handling in Go is different from other languages, and the design philosophy is different. Developers often complain about error handling in Go.

This section starts from the error of the built-in library, combined with the common error handling methods of the built-in library, summarizes the error handling methods suitable for the project.

The outline

  • Your own common error handling methods
  • Error implemented by the built-in library
  • conclusion

Summary of their own common error handling methods

1. Create a value of error type

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

These two methods can be implemented.

package main

import (
	"errors"
	"fmt"
	"reflect"
)

func main() {

	recordError := errors.New("record not found")
	dbError := fmt.Errorf("%s"."db connet fail")
	fmt.Println(recordError, reflect.TypeOf(recordError))
	fmt.Println(dbError, reflect.TypeOf(dbError))

}
>>
record not found *errors.errorString
db connet fail *errors.errorString

Copy the code

2. Customize error types

  • Implementing the Error interface
type CodeError struct {
	Code    int
	Message string
}

func (c CodeError) Error() string {
	return fmt.Sprintf(" e.Code = %d, e.Message=%s", c.Code, c.Message)
}

func Result() error {
	var codeError CodeError
	codeError = CodeError{
		Code:    400,
		Message: "connect fail",}return codeError
}

func main(){
    
    var codeError CodeError
	var err error
	codeError = CodeError{
		Code:    404,
		Message: "http status code error",
	}
	err = codeError
    fmt.Println(err)
}
>>
e.Code = 404, e.Message=http status code error
Copy the code

Error type, as long as the error interface can be implemented.

Take a look at the interface definition:

type error interface {
	Error() string
}

Copy the code
  • The concrete implementation of errors.New

func New(text string) error {
	return &errorString{text}
}

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

func (e *errorString) Error() string {
	return e.s
}
Copy the code

That is, the errorString structure is defined and the Error method is bound

  • The implementation of FMT.Errorf
func Errorf(format string, a ... interface{}) error {return errors.New(Sprintf(format, a...))
}
Copy the code

Errorf also calls errors.New.

To sum up:

  1. There are two ways to create an error
  2. At the bottom is a structure that implements the Error interface
  3. Custom Error type, Error method can be implemented

Error implemented by the built-in library

Errors are common and part of the business, so the built-in library implementation will also encounter errors. How to see the built-in library implementation error

1. strconv.Atoi

func main(){
    
    number, err := strconv.Atoi("2992-121")
    fmt.Println(number,err)
}
>>
0 strconv.Atoi: parsing "2992-121": invalid syntax
Copy the code

The underlying implementation is:


type NumError struct {
	Func string // the failing function (ParseBool, ParseInt, ParseUint, ParseFloat)
	Num  string // the input
	Err  error  // the reason the conversion failed (e.g. ErrRange, ErrSyntax, etc.)
}

func (e *NumError) Error() string {
	return "strconv." + e.Func + ":" + "parsing " + Quote(e.Num) + ":" + e.Err.Error()
}
Copy the code

Define various error types:


var ErrRange = errors.New("value out of range")
var ErrSyntax = errors.New("invalid syntax")
func syntaxError(fn, str string) *NumError {
	return &NumError{fn, str, ErrSyntax}
}

func rangeError(fn, str string) *NumError {
	return &NumError{fn, str, ErrRange}
}

func baseError(fn, str string, base int) *NumError {
	return &NumError{fn, str, errors.New("invalid base " + Itoa(base))}
}

func bitSizeError(fn, str string, bitSize int) *NumError {
	return &NumError{fn, str, errors.New("invalid bit size " + Itoa(bitSize))}
}
Copy the code

That is, the core defines a structure that implements the error interface

2. net/http

func main(){
    
	response, err := http.Get("https://space.bilibili.com/10056291/#/")
	fmt.Println(response, err)
    
}

Copy the code

The underlying error types are:


type Error struct {
	Op  string
	URL string
	Err error
}

func (e *Error) Error() string { return e.Op + "" + e.URL + ":" + e.Err.Error() }

Copy the code

That is, a structure is defined to implement the error interface.

In view of reading the underlying error type in the built-in library, modify your own error type setting method


type ExampleError struct {
	Err     error
	Code    int
	Message string
}

func (e *ExampleError) Error() string {
	return fmt.Sprintf("e.Code = %d e.Err = %s e.Message = %s", e.Code, e.Err.Error(), e.Message)
}

func ExampleResult() error {
	return &ExampleError{
		Err:     errors.New("what the fucking life"),
		Code:    502,
		Message: "what the fucking life",}}Copy the code

conclusion

  • There are two ways to create an error value
  • The Error type that oneself define, need to realize Error method only, realize Error interface can

Others: Here are some suggestions for error handling

  • For each library, common errors can be declared at the beginning of the library file

var ErrorIndexOut = errors.New("index out of range")
var ErrorFuck = errors.New("fucking life")
Copy the code
  • Variables of the wrong type can be takenErrorErrormark
  • It is recommended that error types be handled uniformly, that is, complete projects declare their own library handling modules, rather than randomly creating errors within the project

After < >

  • The first iteration of back end engineer walkthrough is underway