Use w3m for archiving

This commit is contained in:
David Eisinger
2024-01-17 12:04:56 -05:00
parent c5f0c6161a
commit ae64f3eb0a
80 changed files with 28830 additions and 29811 deletions

View File

@@ -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 APIs 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 APIs 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 its tempting to skip one, you might
not expect that error to ever happen. But thats why its an exception!
You need to handle it so that you can find out clearly if it ever does
happen.
Always handle errors. Sometimes its tempting to skip one, you might not expect
that error to ever happen. But thats why its an exception! You need to handle
it so that you can find out clearly if it ever does happen.
If you dont 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 dont 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
layers responsibility and dont 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 layers responsibility and dont
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-funcs, it can be annoying
to return the error. But if you dont 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-funcs, it can be annoying to
return the error. But if you dont 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 isnt necessary and its better to just return the error
unwrapped.
Usually this isnt 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
dont 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 dont 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