3 ms·
>Except when you do (1), your "wrapped" error can longer be compared But that's wrong. When you call String() on it, it will look like the error is just a conc
by c7DJTLrn 4y ago
>Except when you do (1), your "wrapped" error can longer be compared
But that's wrong. When you call String() on it, it will look like the error is just a concatenated string, but it preserves all information about the underlying error, that's the whole point of the %w directive.
https://go.dev/play/p/ZUGCKJDs9N5 https://go.dev/play/p/ZUGCKJDs9N5
- nemothekid 4y agoNo; I don't mean the underlying error. I mean the wrapped error. Let's say I'm writing an API client that uses net/http underneath - func CreateUser(username string, password string) error { _, err := client.Get("https://myapi.com"); return fmt.Errorf("Failed to create: %w", err) } Then I create another method like so: func SSOLogin(provider interface{}, token string) error { user, pass, err = provider.login(); if err != nil { return fmt.Errorf("Failed to login: %w", err) } if err := CreateUser(user, pass); err != nil { return fmt.Errorf("Failed to create: %w", err) } } There is no way for the API consumer to discover if the error happened at provider.login() or CreateUser (except for calling String, and Finding "Failed to create". The wrapping is one layer deep, and to go any further you must create your own types. This commonly happens in larger codebases; and what happens is you must define your own error types if you expect your code to be consumed by others. To be clear, there are way to solve this (creating your own types), but I don't think go handles that better than Rust, and the tools that Go does give you push developers in wrapping/concatenating errors into rather opaque types (which is mostly fine for webservers, you can just throw an error 500 and expect the user to try again). But that, plus `if err == nil` makes error handling in Go rather sore IMO. It's easy for developers to write, but not for library users to use, or for later users to maintain.