> On Feb 3, 2025, at 6:01 AM, Byungjun You <schiz...@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 <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 <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 
<https://go.dev/blog/errors-are-values>
[2] 
https://github.com/golang/go/blob/beea7c1ba6a93c2a2991e79936ac4050bae851c4/src/io/io.go#L44
 
<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/94A57D56-A71C-48A1-B279-D638E178FD6B%40newclarity.net.

Reply via email to