Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> Go has a unique approach to error handling, with a combination of explicit error values and an exception-like panic mechanism.

I don't think that's very unique in itself, although Go's particular quirks might be.



At least around the mainstream languages, I find the try/catch construct (where errors are treated very differently than return codes) much more prevalent. C‘s hacky -1 style perverted error codes don‘t really count for me. And where you have error return values by convention (like Node.JS), these are on top of this, so calling library code isn‘t guaranteed to not error out synchronously as well.


I guess you haven't used rust, or ocaml, or haskell.

In those cases, errors are even more like normal values because they're returned using generic types (Optional/Maybe, Result/Either), not using hacky multiple return stuff.

For example, in go you might have a function that returns (string, error), but you can't define a method on that type that was returned, so e.g. you can't have:

    func (tuple (string, error)) OrElse(val string) string {
        if tuple.1 == nil {
            return tuple.0
        } else {
            return val
        }
    }

This would let you right such code as:

    hostname := os.Hostname().OrElse("localhost")
On the other hand, in rust or haskell you'd return a generic sum type which is either an error or a value and which can be treated as an actually normal value.

This leads to the languages I mentioned above having the ability to have much cleaner and more concise error handling than go.

The fact that go has multiple returns, not tuples or sum types, results in its errors being really awkward to use values, among their other flaws.


  > hostname := os.Hostname().OrElse("localhost")
You could do the following:

  type maybeString struct {
    val string
    err error
  }
  
  func MaybeString(val string, err error) maybeString {
    return maybeString{val, err}
  }

  func (m maybeString) OrElse(defaultValue string) string {
    //...as above...
  }
Then you can do:

  hostname := MaybeString(os.Hostname()).OrElse("localhost")
Of course, this is not practical on a large scale since you don't have generic types and thus would need to `go generate` one instance of the above for each MaybeXXX type. At this point, you're probably better off just writing

  hostname, err := os.Hostname()
  if err != nil {
    hostname = "localhost"
  }


This (optional types) is one thing I'd really like them to explore for go 2.


Yes, a fix to the mess error handling in Go is is long overdue, and I find Rust and Haskell approach one of the most effective ones, clear to understand and not too verbose, and yet powerful and relatively free of the mess exceptions are in other languages. I sincerely hope the Go authors will give sum types a shot in future releases of the languages, because they are so comically powerful that implementing them just feels like the right thing to do.


The generalization (sum types) would be even more powerful. Fingers crossed.


OCaml and Haskell do have exceptions, though.


The Go's way is an almost verbatim copy of the usual Bash and Perl error handlers. It's clearly based on C, with some improvements, but achieved almost the exact same format by coincidence.

(Both Bash and Perl would very likely have the same syntax as Go if they had tuples.)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: