Use w3m for archiving
This commit is contained in:
@@ -1,71 +1,65 @@
|
||||
[1]Stephen's Tech Blog
|
||||
[1]Stephen's Tech Blog
|
||||
|
||||
* [2]Webhook Wizard 🧙♂️
|
||||
• [2]Webhook Wizard 🧙♂️
|
||||
|
||||
Gopher Wrangling. Effective error handling in Go
|
||||
Gopher Wrangling. Effective error handling in Go
|
||||
|
||||
June 19, 2023 · 4 min · Stephen Nancekivell
|
||||
June 19, 2023 · 4 min · Stephen Nancekivell
|
||||
Table of Contents
|
||||
|
||||
Table of Contents
|
||||
□ [3]Guiding principle
|
||||
• [4]1. Always handle errors
|
||||
• [5]2. Log errors in one layer
|
||||
• [6]3. Returning async errors
|
||||
• [7]4. Wrapping errors
|
||||
• [8]5. Downgrade errors Warnings
|
||||
|
||||
* [3]Guiding principle
|
||||
When programming in Go, the amount of error handling is something that slaps
|
||||
you in the face. Most API’s you deal with will expose errors. It can become
|
||||
overwhelming, but with a few tips and a guiding principle we can make handling
|
||||
errors easy, keep our code clean and give you the confidence that nothing is
|
||||
breaking in production.
|
||||
|
||||
[4]1. Always handle errors
|
||||
A cartoon of a crazy stressed programmer pulling their hair out in front of
|
||||
lots of screens showing a error exclamation marks
|
||||
|
||||
[5]2. Log errors in one layer
|
||||
|
||||
[6]3. Returning async errors
|
||||
|
||||
[7]4. Wrapping errors
|
||||
|
||||
[8]5. Downgrade errors Warnings
|
||||
|
||||
When programming in Go, the amount of error handling is something that
|
||||
slaps you in the face. Most API’s you deal with will expose errors. It
|
||||
can become overwhelming, but with a few tips and a guiding principle we
|
||||
can make handling errors easy, keep our code clean and give you the
|
||||
confidence that nothing is breaking in production.
|
||||
|
||||
A cartoon of a crazy stressed programmer pulling their hair out in
|
||||
front of lots of screens showing a error exclamation marks
|
||||
|
||||
A cartoon of a crazy stressed programmer pulling their hair out in
|
||||
front of lots of screens showing a error exclamation marks
|
||||
A cartoon of a crazy stressed programmer pulling their hair out in front of
|
||||
lots of screens showing a error exclamation marks
|
||||
|
||||
Guiding principle[9]#
|
||||
|
||||
The goal for our error handling strategy is that it should require
|
||||
minimal effort and provide an easy way to debug any errors that do
|
||||
occur.
|
||||
The goal for our error handling strategy is that it should require minimal
|
||||
effort and provide an easy way to debug any errors that do occur.
|
||||
|
||||
We wont cover strategies like retrying because they are less common and
|
||||
also expose errors.
|
||||
We wont cover strategies like retrying because they are less common and also
|
||||
expose errors.
|
||||
|
||||
1. Always handle errors[10]#
|
||||
|
||||
Always handle errors. Sometimes it’s tempting to skip one, you might
|
||||
not expect that error to ever happen. But that’s why it’s an exception!
|
||||
You need to handle it so that you can find out clearly if it ever does
|
||||
happen.
|
||||
Always handle errors. Sometimes it’s tempting to skip one, you might not expect
|
||||
that error to ever happen. But that’s why it’s an exception! You need to handle
|
||||
it so that you can find out clearly if it ever does happen.
|
||||
|
||||
If you don’t handle the error, the expected value will be something
|
||||
else and just lead to another error that will be harder to debug, or
|
||||
worse it could lead to data corruption.
|
||||
If you don’t handle the error, the expected value will be something else and
|
||||
just lead to another error that will be harder to debug, or worse it could lead
|
||||
to data corruption.
|
||||
|
||||
In most cases to handle the error all you need to do is return it to
|
||||
the caller of your method, where they can log it.
|
||||
In most cases to handle the error all you need to do is return it to the caller
|
||||
of your method, where they can log it.
|
||||
|
||||
For example, when refreshing some data you might load it, then save it.
|
||||
If you skip the error handling it could overwrite potentially useful
|
||||
data with corrupt data.
|
||||
For example, when refreshing some data you might load it, then save it. If you
|
||||
skip the error handling it could overwrite potentially useful data with corrupt
|
||||
data.
|
||||
|
||||
👎 Bad error handling
|
||||
|
||||
👎 Bad error handling
|
||||
func refresh() {
|
||||
bytes, _ := loadData()
|
||||
saveData(bytes)
|
||||
}
|
||||
|
||||
👍 Good error handling
|
||||
👍 Good error handling
|
||||
|
||||
func refresh() error {
|
||||
bytes, err := loadData()
|
||||
if err != nil {
|
||||
@@ -76,19 +70,19 @@ func refresh() error {
|
||||
|
||||
2. Log errors in one layer[11]#
|
||||
|
||||
You always want to log your errors, ideally to something that will
|
||||
notify you about the error, so you can fix it. There is no point
|
||||
logging the error multiple times at every layer. Make it the top
|
||||
layer’s responsibility and don’t log in any services or lower level
|
||||
code.
|
||||
You always want to log your errors, ideally to something that will notify you
|
||||
about the error, so you can fix it. There is no point logging the error
|
||||
multiple times at every layer. Make it the top layer’s responsibility and don’t
|
||||
log in any services or lower level code.
|
||||
|
||||
Make sure your logging framework is including stack traces so you can
|
||||
trace the error to its cause.
|
||||
Make sure your logging framework is including stack traces so you can trace the
|
||||
error to its cause.
|
||||
|
||||
For example in a web app you would log the error in the http handler
|
||||
when returning the Internal Server status code.
|
||||
For example in a web app you would log the error in the http handler when
|
||||
returning the Internal Server status code.
|
||||
|
||||
👍 Good error handling
|
||||
|
||||
👍 Good error handling
|
||||
func refresh() error {
|
||||
bytes, err := loadData()
|
||||
if err != nil {
|
||||
@@ -97,8 +91,7 @@ func refresh() error {
|
||||
saveData(bytes)
|
||||
}
|
||||
|
||||
func (h *handlers) handleRefreshRequest(w http.ResponseWriter, r *http.Request)
|
||||
{
|
||||
func (h *handlers) handleRefreshRequest(w http.ResponseWriter, r *http.Request) {
|
||||
err := refresh()
|
||||
if err != nil {
|
||||
log.Error("unexpected error processing request %w", err)
|
||||
@@ -111,12 +104,12 @@ func (h *handlers) handleRefreshRequest(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
3. Returning async errors[12]#
|
||||
|
||||
When processing data concurrently using a go-func’s, it can be annoying
|
||||
to return the error. But if you don’t your app will be less
|
||||
maintainable. To handle async errors, return them via a channel to the
|
||||
calling thread.
|
||||
When processing data concurrently using a go-func’s, it can be annoying to
|
||||
return the error. But if you don’t your app will be less maintainable. To
|
||||
handle async errors, return them via a channel to the calling thread.
|
||||
|
||||
👎 Bad error handling
|
||||
|
||||
👎 Bad error handling
|
||||
func refreshManyConcurrently() {
|
||||
go func(){
|
||||
refresh(1)
|
||||
@@ -127,7 +120,8 @@ func refreshManyConcurrently() {
|
||||
}()
|
||||
}
|
||||
|
||||
👍 Good error handling
|
||||
👍 Good error handling
|
||||
|
||||
func refreshManyConcurrently() error {
|
||||
errors := make(chan error, 2)
|
||||
go func(){
|
||||
@@ -140,8 +134,9 @@ func refreshManyConcurrently() error {
|
||||
return multierror.Combine(<-errors, <- errors)
|
||||
}
|
||||
|
||||
When calling functions that return a value and a possible error using a
|
||||
type like Result[T], to wrap the response to pass on the channel.
|
||||
When calling functions that return a value and a possible error using a type
|
||||
like Result[T], to wrap the response to pass on the channel.
|
||||
|
||||
type Result[T any] struct {
|
||||
Value T
|
||||
Error error
|
||||
@@ -149,29 +144,27 @@ type Result[T any] struct {
|
||||
|
||||
4. Wrapping errors[13]#
|
||||
|
||||
Sometimes you want to add additional context to an error message. Eg to
|
||||
include the id of the request that caused the error. You can use
|
||||
fmt.error for this.
|
||||
Sometimes you want to add additional context to an error message. Eg to include
|
||||
the id of the request that caused the error. You can use fmt.error for this.
|
||||
|
||||
err := saveToDb(user)
|
||||
if err != nil {
|
||||
return fmt.errorf("unexpected error saving user. userId=%v error=%w", user.I
|
||||
d, err)
|
||||
return fmt.errorf("unexpected error saving user. userId=%v error=%w", user.Id, err)
|
||||
}
|
||||
|
||||
Usually this isn’t necessary and its better to just return the error
|
||||
unwrapped.
|
||||
Usually this isn’t necessary and its better to just return the error unwrapped.
|
||||
|
||||
5. Downgrade errors Warnings[14]#
|
||||
|
||||
There are types of errors that regularly occur during normal operation.
|
||||
The system might not be able to prevent them all the time, but they
|
||||
don’t need to investigate every time. It is better to treat them as
|
||||
warnings rather than errors. These might be for things like timeouts or
|
||||
intermittent connection errors.
|
||||
There are types of errors that regularly occur during normal operation. The
|
||||
system might not be able to prevent them all the time, but they don’t need to
|
||||
investigate every time. It is better to treat them as warnings rather than
|
||||
errors. These might be for things like timeouts or intermittent connection
|
||||
errors.
|
||||
|
||||
👍 Good error handling
|
||||
func (h *handlers) handleRefreshRequest(w http.ResponseWriter, r *http.Request)
|
||||
{
|
||||
👍 Good error handling
|
||||
|
||||
func (h *handlers) handleRefreshRequest(w http.ResponseWriter, r *http.Request) {
|
||||
err := refresh()
|
||||
if err != nil {
|
||||
if err == context.DeadlineExceeded {
|
||||
@@ -187,43 +180,40 @@ func (h *handlers) handleRefreshRequest(w http.ResponseWriter, r *http.Request)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
[15]« Prev
|
||||
PDFs on the Fly: Programmatically Transforming Webpages into PDFs
|
||||
[16]Next »
|
||||
How to Serve Web Sockets with Http4s
|
||||
[15]« Prev
|
||||
PDFs on the Fly: Programmatically Transforming Webpages into PDFs [16]Next »
|
||||
How to Serve Web Sockets with Http4s
|
||||
[17][18][19][20][21][22]
|
||||
[23]© 2023 [24]Stephen's Tech Blog
|
||||
[25][26][27][28]
|
||||
|
||||
© 2023 [17]Stephen's Tech Blog
|
||||
References:
|
||||
|
||||
References
|
||||
|
||||
Visible links:
|
||||
1. https://stephenn.com/
|
||||
2. https://webhookwizard.com/
|
||||
3. https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#guiding-principle
|
||||
4. https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#1-always-handle-errors
|
||||
5. https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#2-log-errors-in-one-layer
|
||||
6. https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#3-returning-async-errors
|
||||
7. https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#4-wrapping-errors
|
||||
8. https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#5-downgrade-errors-warnings
|
||||
9. https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#guiding-principle
|
||||
10. https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#1-always-handle-errors
|
||||
11. https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#2-log-errors-in-one-layer
|
||||
12. https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#3-returning-async-errors
|
||||
13. https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#4-wrapping-errors
|
||||
14. https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#5-downgrade-errors-warnings
|
||||
15. https://stephenn.com/2023/06/pdfs-on-the-fly-programmatically-transforming-webpages-into-pdfs/
|
||||
16. https://stephenn.com/2022/07/web-sockets-with-http4s/
|
||||
17. https://stephenn.com/
|
||||
|
||||
Hidden links:
|
||||
19. https://twitter.com/intent/tweet/?text=Gopher%20Wrangling.%20Effective%20error%20handling%20in%20Go&url=https%3a%2f%2fstephenn.com%2f2023%2f06%2fgopher-wrangling.-effective-error-handling-in-go%2f&hashtags=
|
||||
20. https://www.linkedin.com/shareArticle?mini=true&url=https%3a%2f%2fstephenn.com%2f2023%2f06%2fgopher-wrangling.-effective-error-handling-in-go%2f&title=Gopher%20Wrangling.%20Effective%20error%20handling%20in%20Go&summary=Gopher%20Wrangling.%20Effective%20error%20handling%20in%20Go&source=https%3a%2f%2fstephenn.com%2f2023%2f06%2fgopher-wrangling.-effective-error-handling-in-go%2f
|
||||
21. https://reddit.com/submit?url=https%3a%2f%2fstephenn.com%2f2023%2f06%2fgopher-wrangling.-effective-error-handling-in-go%2f&title=Gopher%20Wrangling.%20Effective%20error%20handling%20in%20Go
|
||||
22. https://facebook.com/sharer/sharer.php?u=https%3a%2f%2fstephenn.com%2f2023%2f06%2fgopher-wrangling.-effective-error-handling-in-go%2f
|
||||
23. https://api.whatsapp.com/send?text=Gopher%20Wrangling.%20Effective%20error%20handling%20in%20Go%20-%20https%3a%2f%2fstephenn.com%2f2023%2f06%2fgopher-wrangling.-effective-error-handling-in-go%2f
|
||||
24. https://telegram.me/share/url?text=Gopher%20Wrangling.%20Effective%20error%20handling%20in%20Go&url=https%3a%2f%2fstephenn.com%2f2023%2f06%2fgopher-wrangling.-effective-error-handling-in-go%2f
|
||||
25. https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#top
|
||||
26. https://github.com/stephennancekivell
|
||||
27. https://twitter.com/hi_stephen_n
|
||||
28. https://www.linkedin.com/in/stephen-nancekivell-77003039
|
||||
29. https://stackoverflow.com/users/893854/stephen
|
||||
[1] https://stephenn.com/
|
||||
[2] https://webhookwizard.com/
|
||||
[3] https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#guiding-principle
|
||||
[4] https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#1-always-handle-errors
|
||||
[5] https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#2-log-errors-in-one-layer
|
||||
[6] https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#3-returning-async-errors
|
||||
[7] https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#4-wrapping-errors
|
||||
[8] https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#5-downgrade-errors-warnings
|
||||
[9] https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#guiding-principle
|
||||
[10] https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#1-always-handle-errors
|
||||
[11] https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#2-log-errors-in-one-layer
|
||||
[12] https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#3-returning-async-errors
|
||||
[13] https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#4-wrapping-errors
|
||||
[14] https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#5-downgrade-errors-warnings
|
||||
[15] https://stephenn.com/2023/06/pdfs-on-the-fly-programmatically-transforming-webpages-into-pdfs/
|
||||
[16] https://stephenn.com/2022/07/web-sockets-with-http4s/
|
||||
[17] https://twitter.com/intent/tweet/?text=Gopher%20Wrangling.%20Effective%20error%20handling%20in%20Go&url=https%3a%2f%2fstephenn.com%2f2023%2f06%2fgopher-wrangling.-effective-error-handling-in-go%2f&hashtags=
|
||||
[18] https://www.linkedin.com/shareArticle?mini=true&url=https%3a%2f%2fstephenn.com%2f2023%2f06%2fgopher-wrangling.-effective-error-handling-in-go%2f&title=Gopher%20Wrangling.%20Effective%20error%20handling%20in%20Go&summary=Gopher%20Wrangling.%20Effective%20error%20handling%20in%20Go&source=https%3a%2f%2fstephenn.com%2f2023%2f06%2fgopher-wrangling.-effective-error-handling-in-go%2f
|
||||
[19] https://reddit.com/submit?url=https%3a%2f%2fstephenn.com%2f2023%2f06%2fgopher-wrangling.-effective-error-handling-in-go%2f&title=Gopher%20Wrangling.%20Effective%20error%20handling%20in%20Go
|
||||
[20] https://facebook.com/sharer/sharer.php?u=https%3a%2f%2fstephenn.com%2f2023%2f06%2fgopher-wrangling.-effective-error-handling-in-go%2f
|
||||
[21] https://api.whatsapp.com/send?text=Gopher%20Wrangling.%20Effective%20error%20handling%20in%20Go%20-%20https%3a%2f%2fstephenn.com%2f2023%2f06%2fgopher-wrangling.-effective-error-handling-in-go%2f
|
||||
[22] https://telegram.me/share/url?text=Gopher%20Wrangling.%20Effective%20error%20handling%20in%20Go&url=https%3a%2f%2fstephenn.com%2f2023%2f06%2fgopher-wrangling.-effective-error-handling-in-go%2f
|
||||
[23] https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/#top
|
||||
[24] https://stephenn.com/
|
||||
[25] https://github.com/stephennancekivell
|
||||
[26] https://twitter.com/hi_stephen_n
|
||||
[27] https://www.linkedin.com/in/stephen-nancekivell-77003039
|
||||
[28] https://stackoverflow.com/users/893854/stephen
|
||||
|
||||
Reference in New Issue
Block a user