This repository was archived by the owner on Feb 8, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy path12-errors.slide
More file actions
228 lines (146 loc) · 5.53 KB
/
12-errors.slide
File metadata and controls
228 lines (146 loc) · 5.53 KB
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
Errors in Go
Gerrit Renker
22 Feb 2017
Tags: edmontongo, golang, workshop
* Talk Structure
1. Introduction
2. Errors in Go
3. Handling
4. Patterns & Policies
5. Exercises
"Knowledge rests not upon truth alone, but upon error also."
Carl Jung
* 1. Introduction
* Errors are inevitable, handling them not
- typically during function/method execution
- precondition not met - changing conditions
- incomplete knowledge
- human mistake
: *Failure*is*an*expected*condition.*
"Mistakes are a fact of life. It is the response to the error that counts."
N. Giovanni
* Errors in Go vs other languages
*C*:
- no fixed convention (`NULL`, `-1`, `errno`, `ERRPTR()`, ...)
- frequent use of `goto`
*Java/Python*: `exceptions`
- avoid `goto` problem
- _interfere_with_normal_control_flow_ (`try` .. `{` `try` .. `{` `try` ... `{` ... `catch` ...)
- complex stack traces
*Go*: _errors_are_values_
- simple concept (Pike: [[https://talks.golang.org/2015/simplicity-is-complicated.slide#1]["Simplicity is hard"]])
- _integrate_better_in_normal_control_flow_
- allow/require user to define policy
"Simplicity is prerequisite for reliability." -- E.W. Dijkstra
* 2. Errors In Go
* Proverb 1: Errors are values
Dedicated value/variable:
value, ok := myHashMap["key"]
if !ok {
// key error
}
More frequently:
file, err := os.Open("/etc/passwd")
if err != nil {
log.Fatalf("Failed to open file: %s", err)
}
* Proverb 1: Errors Are Values
_Interface_Definition_:
type error interface {
Error() string
}
* Proverb 1: Errors Are Values
_Interface_Definition_:
type error interface {
Error() string
}
_Go_stdlib_:
// errorString is a trivial implementation of error.
type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}
* Go errors package
// Package errors implements functions to manipulate errors.
package errors
type errorString struct {
s string
}
func New(text string) error {
return &errorString{text}
}
*Usage*:
.play -edit 12-errors/errors_package.go /oops!/,/Annotated/
* 3. Handling - Proverb 2: Don't just check errors, handle them gracefully
* 3.1 Propagation
.image 12-errors/images/unexpected-error.jpg _ 400
* 3.1 Propagation
By _chaining_ annotations:
.play -edit 12-errors/annotations.go /func foo/,
* 3.2 Retry
.play -edit 12-errors/retry.go /func main/,
Good for _temporary_condition_ (503 - _Service_Unavailable_)
* 3.3 Exit or at least log problems
.play -edit 12-errors/exit_and_log.go /fatal/,
- more elaborate variant
- based on _type_assertion_
* Proverb 3: Don't panic
- Erlang "let it crash" has no Go counterpart
- single `panic` brings entire program down
.play -edit 12-errors/panic.go /func main/,
* 4. Patterns & Policies
* 4.1 "Happy Path"
val, err := ComputeClickCounts()
if err != nil {
log.Fatalf("failed to get user stats: %s", err)
}
acc, err := IntegrateTimeSeries(time.Now(), val)
if err != nil {
log.Fatalf("value error in integration: %s", err)
}
total, err := ExtractTotals(acc)
if err != nil {
log.Fatalf("numbers don't add up: %s", err)
}
fmt.Println("Your monthly credit card bill will be", total)
* 4.2 Track error internally
.play -edit 12-errors/scanner.go /const/,
* 4.3 Test behaviour, not literal value
Error _value_literals_ are brittle:
.play -edit 12-errors/eof.go /This/,/^\s+}/
Test for _behaviour_ instead (`os`):
func IsExist(err error) bool
func IsNotExist(err error) bool
func IsPermission(err error) bool
Similar (`net` package):
func (e *DNSError) Temporary() bool // temporary problem - retry!
func (e *DNSError) Timeout() bool // lookup timed out
* 5. Conclusion
- Go errors are simple values
- Building blocks for larger abstractions
* 5. Exercises
1. Go panics on divide-by-zero. Define a numeric `DividerErr` error type,
which returns "invalid number" if the corresponding number is 0.
// IntDivide returns integral num/denom and the remainder.
func IntDivide(num, denom int) (div, rem int, err error) {
if denom == 0 {
return 0, 0, DivideErr(denom)
}
return num/denom, num%denom, nil
}
.link https://play.golang.org/p/LXjxU_J4-K
2. Syscall.Errno contains error values that are typical on Linux/Unix servers.
Create a wrapper `struct` `ConnectionError` which implements
func (c ConnectionError) Timeout() bool // true for syscall.ETIMEDOUT
func (c ConnectionError) Temporary() bool // true for syscall.EBUSY, syscall.EINPROGRESS
func (c ConnectionError) IsFatal() bool // true for syscall.EHOSTDOWN, syscall.ENOTRECOVERABLE
.link https://play.golang.org/p/00bJqeBq1a
* Resources
- [[http://www.se-radio.net/2017/01/se-radio-episode-280-gerald-weinberg-on-bugs-errors-and-software-quality/][Gerald Weinberg on Bugs Errors and Software Quality]]
- [[https://go-proverbs.github.io/][Go Proverbs]] ([[https://www.youtube.com/watch?v=PAAkCSZUG1c][video]])
- [[https://blog.golang.org/error-handling-and-go][Error handling and Go]]
- [[https://blog.golang.org/defer-panic-and-recover][Defer, Panic, and Recover]]
- Going Go - Error Handling [[https://www.goinggo.net/2014/10/error-handling-in-go-part-i.html][Part 1]], [[https://www.goinggo.net/2014/11/error-handling-in-go-part-ii.html][Part 2]]
- Example of accumulating error internally: [[https://github.com/RobotsAndPencils/buford][Buford]] file [[https://github.com/RobotsAndPencils/buford/blob/master/pushpackage/pushpackage.go][pushpackage.go]] ([[https://github.com/RobotsAndPencils/buford#website-push][usage]])