Add go link
This commit is contained in:
@@ -15,6 +15,10 @@ references:
|
|||||||
url: https://medium.com/golang-learn/go-project-layout-e5213cdcfaa2
|
url: https://medium.com/golang-learn/go-project-layout-e5213cdcfaa2
|
||||||
date: 2023-06-13T15:00:02Z
|
date: 2023-06-13T15:00:02Z
|
||||||
file: medium-com-efpmux.txt
|
file: medium-com-efpmux.txt
|
||||||
|
- title: "Gopher Wrangling. Effective error handling in Go | Stephen's Tech Blog"
|
||||||
|
url: https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/
|
||||||
|
date: 2023-06-20T16:25:12Z
|
||||||
|
file: stephenn-com-kbiijs.txt
|
||||||
---
|
---
|
||||||
|
|
||||||
I find [Go][1] really compelling, even though it's not super applicable to my job. When evaluating a new tool, I find I'm weirdly biased to things written in Go.
|
I find [Go][1] really compelling, even though it's not super applicable to my job. When evaluating a new tool, I find I'm weirdly biased to things written in Go.
|
||||||
@@ -66,9 +70,11 @@ I find [Go][1] really compelling, even though it's not super applicable to my jo
|
|||||||
* [Why David Yach Loves Go][10]
|
* [Why David Yach Loves Go][10]
|
||||||
* [One process programming notes (with Go and SQLite)][11]
|
* [One process programming notes (with Go and SQLite)][11]
|
||||||
* [Go Project Layout][12]
|
* [Go Project Layout][12]
|
||||||
|
* [Gopher Wrangling. Effective error handling in Go][13]
|
||||||
|
|
||||||
[8]: https://github.com/golang-standards/project-layout
|
[8]: https://github.com/golang-standards/project-layout
|
||||||
[9]: https://changelog.com/gotime/278
|
[9]: https://changelog.com/gotime/278
|
||||||
[10]: https://cloud.google.com/blog/products/application-modernization/why-david-yach-loves-go
|
[10]: https://cloud.google.com/blog/products/application-modernization/why-david-yach-loves-go
|
||||||
[11]: https://crawshaw.io/blog/one-process-programming-notes
|
[11]: https://crawshaw.io/blog/one-process-programming-notes
|
||||||
[12]: https://medium.com/golang-learn/go-project-layout-e5213cdcfaa2
|
[12]: https://medium.com/golang-learn/go-project-layout-e5213cdcfaa2
|
||||||
|
[13]: https://stephenn.com/2023/06/gopher-wrangling.-effective-error-handling-in-go/
|
||||||
|
|||||||
226
static/archive/stephenn-com-kbiijs.txt
Normal file
226
static/archive/stephenn-com-kbiijs.txt
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
[1]Stephen's Tech Blog
|
||||||
|
|
||||||
|
* [2]Webhook Wizard 🧙♂️
|
||||||
|
|
||||||
|
Gopher Wrangling. Effective error handling in Go
|
||||||
|
|
||||||
|
June 19, 2023 · 4 min · Stephen Nancekivell
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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
|
||||||
|
func refresh() {
|
||||||
|
bytes, _ := loadData()
|
||||||
|
saveData(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
👍 Good error handling
|
||||||
|
func refresh() error {
|
||||||
|
bytes, err := loadData()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
saveData(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
👍 Good error handling
|
||||||
|
func refresh() error {
|
||||||
|
bytes, err := loadData()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
saveData(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *handlers) handleRefreshRequest(w http.ResponseWriter, r *http.Request)
|
||||||
|
{
|
||||||
|
err := refresh()
|
||||||
|
if err != nil {
|
||||||
|
log.Error("unexpected error processing request %w", err)
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
👎 Bad error handling
|
||||||
|
func refreshManyConcurrently() {
|
||||||
|
go func(){
|
||||||
|
refresh(1)
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func(){
|
||||||
|
refresh(2)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
👍 Good error handling
|
||||||
|
func refreshManyConcurrently() error {
|
||||||
|
errors := make(chan error, 2)
|
||||||
|
go func(){
|
||||||
|
errors <- refresh(1)
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func(){
|
||||||
|
errors <- refresh(2)
|
||||||
|
}()
|
||||||
|
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.
|
||||||
|
type Result[T any] struct {
|
||||||
|
Value T
|
||||||
|
Error error
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
err := saveToDb(user)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.errorf("unexpected error saving user. userId=%v error=%w", user.I
|
||||||
|
d, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
👍 Good error handling
|
||||||
|
func (h *handlers) handleRefreshRequest(w http.ResponseWriter, r *http.Request)
|
||||||
|
{
|
||||||
|
err := refresh()
|
||||||
|
if err != nil {
|
||||||
|
if err == context.DeadlineExceeded {
|
||||||
|
log.Warn("Timeout error processing request %w", err)
|
||||||
|
} else {
|
||||||
|
log.Error("unexpected error processing request %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
|
[15]Next »
|
||||||
|
How to Serve Web Sockets with Http4s
|
||||||
|
|
||||||
|
© 2023 [16]Stephen's Tech Blog
|
||||||
|
|
||||||
|
References
|
||||||
|
|
||||||
|
Visible links:
|
||||||
|
1. https://stephenn.com/
|
||||||
|
2. https://webhookwizard.com/
|
||||||
|
3. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L18069-7455TMP.html#guiding-principle
|
||||||
|
4. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L18069-7455TMP.html#1-always-handle-errors
|
||||||
|
5. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L18069-7455TMP.html#2-log-errors-in-one-layer
|
||||||
|
6. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L18069-7455TMP.html#3-returning-async-errors
|
||||||
|
7. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L18069-7455TMP.html#4-wrapping-errors
|
||||||
|
8. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L18069-7455TMP.html#5-downgrade-errors-warnings
|
||||||
|
9. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L18069-7455TMP.html#guiding-principle
|
||||||
|
10. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L18069-7455TMP.html#1-always-handle-errors
|
||||||
|
11. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L18069-7455TMP.html#2-log-errors-in-one-layer
|
||||||
|
12. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L18069-7455TMP.html#3-returning-async-errors
|
||||||
|
13. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L18069-7455TMP.html#4-wrapping-errors
|
||||||
|
14. file:///var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L18069-7455TMP.html#5-downgrade-errors-warnings
|
||||||
|
15. https://stephenn.com/2022/07/web-sockets-with-http4s/
|
||||||
|
16. https://stephenn.com/
|
||||||
|
|
||||||
|
Hidden links:
|
||||||
|
18. 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=
|
||||||
|
19. 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
|
||||||
|
20. 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
|
||||||
|
21. https://facebook.com/sharer/sharer.php?u=https%3a%2f%2fstephenn.com%2f2023%2f06%2fgopher-wrangling.-effective-error-handling-in-go%2f
|
||||||
|
22. 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
|
||||||
|
23. 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
|
||||||
|
24. file://localhost/var/folders/q9/qlz2w5251kzdfgn0np7z2s4c0000gn/T/L18069-7455TMP.html#top
|
||||||
|
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