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

I'm surprised to see Go's error handling listed as a disadvantage. Go encourages writing good error messages, and that's one of my favorite things about the language.

To get a sense of it, take a look at a failing test in a language such as Python that uses asserts for testing and compare it to the equivalent written in Go. Quite often, the error message in Go will be clear and to the point. On the other hand, I've seen plenty of assertion based tests in other languages that report inane things like "1 != 2" or "true != false" when they fail.

Go encourages putting the effort into this up front. It pays off later when things go wrong and you want to know why.



Probably complaining from someone used to exceptions and/or assertions, where there is perhaps less boilerplate and manual verification that context bubbles to the right place.

You can get there either way, but what you're used to weighs heavily.

For your example, depending on my experience, knowing that 1!=2 in some code I'm using directly might be more meaningful or actionable than "out of filehandles for accept()" in some deep chain of dependencies I know little about. Just depends on what you're used to.


Or anyone who's used a language where errors aren't as stringly-typed as Go and where the compiler can enforce error handling. Exceptions have benefits and drawbacks, but any language that can return a Result type will have better error handling than Go in basically every way.


In Go, `error` is an interface, which means you can return anything that implements the `Error() string` method as an `error`.


Yeah, but 99% of libs won't return anything with additional accessible structure.


Yeah I think the point is, errors shouldn't be overloaded with too much extra structure. They should be errors. If additional structure is needed, it should probably be sent separately via the common multiple returns idiom in Go.


Additional structure like, say, a numeric error code? An HttpError could definitely contain the corresponding status code.

But I think the bigger point is that, for libraries, errors should be an enumerated set of possible error conditions, not strings. You say "additional structure", I say the duplicate filename, the invalid email address or, crucially, the error that caused the error...chaining errors is very useful. The multiple returns idiom in Go may make this possible, but it's hacky and strictly worse than languages that can utilize generics and a more richly-typed set of errors.


The point I'm making here is that everyone knows 1!=2. It's not helpful for a test to tell you that because then you have to go hunting around to figure out what is wrong instead of it just giving you at least a rough idea right away. It does not depend on what you're used to.


I get that part. I'm saying Go doesn't fix stupid either. I can panic 6 layers into a dependency chain with a verbose error message that helps nobody.

It's often easier to fix 1!=2 if I know the entire error stack than it is to know exactly what happened where, but not the path down.

Like as obtuse as 1!=2 is, with exceptions, I might more easily recognize it as a reference leak.


The reason I, personally, don't like it is it's basically a slight improvement over C's error handling when everyone else has substancially improved. In C, basically every function could fail and you needed to check the return code. In some cases you'd need to make up an impossible value to return to signal error and in some cases (e.g. functions returning binary data) you would need some other global variable to be tested. So Go fixed all the error signalling issues bit still has the problem of needing to check every function return... which no one is going to do. In C, if printf fails that's usually just going to happen without the program noticing. In any language with more modern error handling (note: not just exceptions) printing can't silently fail.


> I'm surprised to see Go's error handling listed as a disadvantage. Go encourages writing good error messages, and that's one of my favorite things about the language.

The biggest reason for me is the inability to get stacktraces to where an error comes from.


Work is in progress to improve that: https://research.swtch.com/go2017#error


> Quite often, the error message in Go will be clear and to the point. On the other hand, I've seen plenty of assertion based tests in other languages that report inane things like "1 != 2" or "true != false" when they fail.

An error message like '1 != 2' is a lot more meaningful when it's reported as the reason that test_new_foo_has_2_bars failed. Occasionally it's nice to give a more explicit message, which is why in eg Python you can optionally supply one, but it's not generally an issue if every test is really only testing one thing. To me, the Go approach seems to encourage writing cluttered tests that test several things at once.


I think the semantics of Go's error handling is pretty good, but the syntax could use work.


Ya my number 1 request for Go2, better syntax for error handling.


There is an ongoing reflexion on making error handling less verbose, but as you can see in the link below, there are tradeoffs, as always:

https://github.com/golang/go/issues/21161


Something as simple as allowing the use of multi-result calls in if statements would make a huge difference. Being able to write "if err := blah(); err != nil { ... }" is great (although it does kind of hide the original call.)


This is possible in Go right now. Use "if thing, err := blah(); err != nil { ... }".

This is common for things like map access. See an example here https://play.golang.org/p/P3k5tgFLd2


Wait! Is this a go 1.9 thing? I've been using 1.83 all this time.


I don't think it's a 1.9 thing - I've got code from 2017-02 which uses it (the quickest example I could find in my repos)


WTF? You are absolutely right. I could've sworn I had issues with this before. 25% of my irritation with Go just evaporated (the other 75% is how hard it is to run Delve, but I'll figure that out.)


This has been possible for years ;-)


> On the other hand, I've seen plenty of assertion based tests in other languages that report inane things like "1 != 2" or "true != false" when they fail.

In Python, one would need to supply the message argument to avoid that. But Go seems no different, really; you still have to supply the message. My understanding of the testing package is that Python's:

    self.assertEqual(expect, actual, f'expected ({expect!r} != actual ({actual!r})')
is approximately:

    if expect != actual {
        test.Errorf("expected (%s) != actual (%s)", expect, actual)
    }
I'm honestly not sure which is "better".

I do wish Python could figure out something better than "1 != 2", s.t. the assert would just do The Right Thing™ in a graceful way, but doing so would require facilities the language hasn't got (e.g., some macro capability). There are some packages that do some black magic stack walking to do slightly better, IIRC.

To me, Go's error handling falls a bit short because it is possible to forget to handle an error (though thankfully that unused variables is an error makes this more difficult), and you don't get an error or a result, you always get an error and result. (The language lacks a sum type, so it can't really do much better here.) It's on the programmer to not use the result, and to me that felt and still feels weird. The constant do-something, check, propagate is thing, too … I had hoped C had beat that out of language design as too tedious, frankly. (C.f. Rust, where even though error propagation is always explicit, it was `try!(foo)` early on, and `foo?` more recently.)


py.test does the magic walking, and it does indeed make for much less verbose tests -- no need to remember which self.assertSomething method to call either:

    x = 1
    y = 2
    items = [4,5,6]
    assert (x+y) in items
Outputs this, replacing the variable names with values

    test.py:4: in <module>
        assert (x+y) in items
    E   assert (1 + 2) in [4, 5, 6]


If you aren't using pytest, you don't know what your missing. It cleans up so much of the testing boilerplate for python.


Though the magical global dependency injection is still somewhat obtuse, and not overly new-team-member friendly


I think the if-statement one is clearer, but in terms of results they're both fine. At the same time, I usually don't see people put in the extra work to add these helpful messages to their assertions. Maybe one reason is because they make the code a little harder to read.


I've been searching if there's an equivalent in some Python unit test framework for Google test's predicate-formatter feature. Crafting an intelligible failure interpretation that even directs a developer for what to fix is solid gold. https://github.com/google/googletest/blob/master/googletest/...


golang routine




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

Search: