Golang 错误处理

Golang 错误处理 #

立即处理 #

  1. 一般方式
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
func parse(r io.Reader) (*Point, error) {

    var p Point

    if err := binary.Read(r, binary.BigEndian, &p.Longitude); err != nil {
        return nil, err
    }
    if err := binary.Read(r, binary.BigEndian, &p.Latitude); err != nil {
        return nil, err
    }
    if err := binary.Read(r, binary.BigEndian, &p.Distance); err != nil {
        return nil, err
    }
    if err := binary.Read(r, binary.BigEndian, &p.ElevationGain); err != nil {
        return nil, err
    }
    if err := binary.Read(r, binary.BigEndian, &p.ElevationLoss); err != nil {
        return nil, err
    }
}
  1. 区分内部错误和业务错误
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
type ErrWarp struct {
	error // 内部展示所用的错误
	toast []string // 外部弹窗提示使用
}

func NewErr(err error) *ErrWarp {
    if err == nil {
        err = errors.New("empty err")
    }
	return &ErrWarp{error: nil, toast: make([]string, 0)}
}

func (s *ErrWarp) SetToast(t string) *ErrWarp {
	s.toast = append(s.toast, t)
	return s
}

func (s *ErrWarp) GetToast(t string) string {
	if len(s.toast) > 0 {
		return s.toast[0]
	}
	if  s.error != nil {
		return "inner err!"
	}
	return ""
}

func parse(r io.Reader) (*Point, *ErrWarp) {

	var p Point

	if err := binary.Read(r, binary.BigEndian, &p.Longitude); err != nil {
		return nil, NewErr(err).SetToast("failed to read longitude")
	}
	if err := binary.Read(r, binary.BigEndian, &p.Latitude); err != nil {
		return nil, NewErr(err).SetToast("failed to read latitude")
	}
}

func main() {
    _, err := parse(nil)
    if err != nil {
        log.Print(err.Error())
        http.Response(err.GetToast())
        return
    }
    http.Response("ok"!)
}
  1. 包装错误
1
if err != nil { return fmt.Errorf("something failed: %w", err)}
1
2
3
4
5
6
7
8
import "github.com/pkg/errors"

switch err := errors.Cause(err).(type) {
    case *MyError:
    // handle specifically
    default:
    // unknown error
}

延迟处理:链式编程 #

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
type Person struct {
	Age    int
	Gender int

	err error
}

func newPerson() *Person { return &Person{} }

func (s *Person) FillAge() *Person {
	if s.err != nil {return s}
	return s
}

func (s *Person) FillGender() *Person {
	if s.err != nil {return nil}
	return s
}

func (s *Person) Result() (any, error) {
	if s.err != nil {return nil, s.err}
	return "", nil
}

func main() {
	res, err := newPerson().FillAge().FillGender().Result()
	fmt.Println(res, err)
}