Watch out for that article <https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully> is pretty old, predating stdlib wrapping etc.
On Thu, 6 Feb 2025 at 14:29, Byungjun You <schiz...@gmail.com> wrote: > Hi Mike, thank you so much for sharing your thoughts and all those > resources with concrete examples. Those really help me to understand how > errors in go work and how it is different from errors in Java. > > Based on what you've shared, here's how I understand it: > In essence, because an error in Go is just a value, there’s no built-in > way to signal which specific errors might be returned except through > documentation. However, since an error is a value, we can also enrich it > with additional context like user-friendly messages, stack traces, and more. > Plus, sentinel errors are one way to expose API errors and once we exposed > those to API users, it is very important to stick to it and not to change. > > And I found the below article very interesting. Please check it out when > you have time. > > https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully > > Thank you again for your sharing. > > 2025년 2월 4일 화요일 오전 3시 2분 37초 UTC+9에 Mike Schinkel님이 작성: > > On Feb 3, 2025, at 6:01 AM, Byungjun You <schi...@gmail.com> wrote: > > In Java, checked exceptions allow developers to define in advance which > exceptions a function can throw. However, it seems that Go does not have > such a feature. Would it be considered a best practice in Go to document > the possible errors that an API function can return? Additionally, what are > some best practices that API providers can follow to help API users handle > errors effectively? > > In Go, errors are values[1] meaning most in the Go community frown on > try-catch style exception handling as in Java. > > Each function in Go which can generate an error will typically return that > error as an additional value; e.g.: > > func (d Data) getValue() (value any, err error) { > if d.value == nil { > return nil, errors.New("value as not been set") > } > if reflect.ValueOf(d.value).IsZero() { > return nil, errors.New("value is empty") > } > return value,err > } > > Then getValue() would be called like this: > > value, err := data.getValue() > > See https://go.dev/play/p/PciRk_t_UaV for full working example. > > In some cases — though not as many as I would like — Go developers often > create sentinel values that might look like this: > > var ( > ErrValueNotSet = errors.New("value as not been set") > ErrValueIsEmpty = errors.New("value is empty") > ) > > Then callers can check them using errors.Is() like so: > > if errors.Is(err, ErrValueNotSet) {...} > if errors.Is(err, ErrValueIsEmpty) {...} > > See https://go.dev/play/p/pamY1pcAoVP for a full working example. > > A common sentinel error value from the Go std lib is io.EOF[2] > > However, AFAIK, there is no way programmatically to determine which errors > a Go function might return at this time. It would be nice if there were > some built-in mechanism for doing that using the reflect package, but I > would not expect that to be added as I cannot imagine how it could be > implemented without slowing down compilation. Unfortunately. > > As for best practices, IMO that would be to define sentinel error > variables instead of errors created inline with errors.New() or > fmt.Errorf() for all errors that your function may return, and then use > errors.Join() to join with any errors returned by a function your function > called before returning to the caller. Then document your sentinel error > variables and commit to not renaming or removing them in future versions of > your API. > > Does that answer your question? > > -Mike > [1] https://go.dev/blog/errors-are-values > [2] > https://github.com/golang/go/blob/beea7c1ba6a93c2a2991e79936ac4050bae851c4/src/io/io.go#L44 > > -- > You received this message because you are subscribed to the Google Groups > "golang-nuts" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to golang-nuts+unsubscr...@googlegroups.com. > To view this discussion visit > https://groups.google.com/d/msgid/golang-nuts/f3871600-0bd2-4a91-b94b-f24fa7828a40n%40googlegroups.com > <https://groups.google.com/d/msgid/golang-nuts/f3871600-0bd2-4a91-b94b-f24fa7828a40n%40googlegroups.com?utm_medium=email&utm_source=footer> > . > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/CAA38pebmkiMsji4eRVjoqGirHp_M_FVD5zVnxc%3DNK9hXy3b_qQ%40mail.gmail.com.