LWN.net Logo

Uses

Uses

Posted Mar 28, 2012 22:22 UTC (Wed) by ikm (subscriber, #493)
Parent article: Go version 1 released

A question to LWN readers: what would you use this language for, and why?


(Log in to post comments)

Uses

Posted Mar 28, 2012 22:32 UTC (Wed) by lkundrak (subscriber, #43452) [Link]

It feels very fast, comparable to C, yet is a lot safer than C and comes with very useful library and built in lightweight concurrency.

I myself don't use it very much, about the only thing I used it for was for modelling workload for stress testing a web service we create. I needed to maintain a lot of concurrent user sessions, understand tls, http and json, and I could not find a better tool to do the job.

Uses

Posted Mar 29, 2012 0:00 UTC (Thu) by Cyberax (✭ supporter ✭, #52523) [Link]

I'm using it as a replacement for Python.

Go compilation is _fast_ (really, really fast), so in practice there's no difference in speed between starting Python interpreter and doing full Go compilation. And of course, Go is statically typed.

Other than that:
1) I miss generics.
2) Exceptions in Go are FUBARed.

Uses

Posted Mar 29, 2012 7:10 UTC (Thu) by imgx64 (guest, #78590) [Link]

> 2) Exceptions in Go are FUBARed

Are you using panic/recover like exceptions in other languages? They're not supposed to be used that way; you should use multiple return values instead.

panic()/recover() are usually used:
1- Internally in a package, if you have a long call chain (such as in a recursive descent parser), and adding ", err" to each call is tedious. You can panic on errors, and then catch the panic at the topmost function *and convert it to an error before returning it*. It's unidiomatic to let such panics escape your package.

2- To report genuine *programmer* errors. For example, regexp.MustCompile panics on invalid regular expressions because they are meant to be used with fixed strings (as opposed to regular expressions that are created dynamically or from user input).

Some programmers use recover() to "increase reliability" by catching all possible panics. I find that rather useless, since the whole program will crash if a panic reaches the top of *any goroutine*, and no recover can help. It's usually easier to have a daemon process respawn the program (after logging the crash, of course).

Uses

Posted Mar 29, 2012 10:31 UTC (Thu) by dgm (subscriber, #49227) [Link]

Many people argue that using exceptions as a control flux construct is inherently wrong in any language. I'm not convinced of that, but apparently GO developers are.

Uses

Posted Mar 31, 2012 0:09 UTC (Sat) by cmccabe (guest, #60281) [Link]

I agree. Exceptions should be used for exceptional conditions (null pointer dereference, out-of-bounds access, division by zero.) Basically, things that indicate a programmer mistake. The Go guys got it right.

Using exceptions for control flow is just gross. Just like goto.

Uses

Posted Mar 31, 2012 0:32 UTC (Sat) by Cyberax (✭ supporter ✭, #52523) [Link]

How about 'file not found' during, say, delayed reading of configuration?

Uses

Posted Mar 31, 2012 0:44 UTC (Sat) by cmccabe (guest, #60281) [Link]

"File not found" isn't a programmer error, so it shouldn't cause an exception.

Uses

Posted Mar 31, 2012 0:52 UTC (Sat) by Cyberax (✭ supporter ✭, #52523) [Link]

Ok. You have:

>bool is_propery_set(context, prop_name);

This can cause delayed configuration loading and reading with a potential for FileNotFound error. What are you going to do in this case?

I advise:
> enum Bool { True, False, FileNotFound };

Uses

Posted Mar 31, 2012 1:29 UTC (Sat) by cmccabe (guest, #60281) [Link]

I wouldn't advise calling anything Bool that has more than 2 possible values. Or trying to reimplement primitive types.

A common Go idiom is returning a tuple that includes an error code.

Uses

Posted Mar 31, 2012 5:44 UTC (Sat) by Cyberax (✭ supporter ✭, #52523) [Link]

So your code instead of:
if (is_set(ctx, 'debug_mode') && is_set(ctx,'show_log'))
//   do_something();
Becomes:
(debug_mode, err1) = is_set(ctx, 'debug_mode')
if (err1) return err1;
(show_log, err2) = is_set(ctx, 'show_log')
if (err1) return err1;
if (debug_mode && show_log)
// do_something()
So a one-liner quickly turns into an unreadable ream of error-prone source code.

But let's go further. Suppose I have a lazy-loaded collection that exposes a Map interface. I.e.
map[string,string] m = make_lazy_map(...);

string a = m.get('hello')
The code that works with this map might not even know that it can return errors. What are you going to do in this case?

Exceptions are complex because they solve a complex task. And any attempt to solve it any other way leads to Yet Another Dumb Exception Framework, as Go show us.

Uses

Posted Mar 31, 2012 7:56 UTC (Sat) by fdr (subscriber, #57064) [Link]

If one needs to short circuit for a major fault, use panic/recover. Accrue low-level cleanup actions using defer expressions. Done. I had the same problem you describe and asked some Go-people about it, and then pointed me to a module that used that pattern. It works fine, and doesn't even require a large-scale understanding of the code using said pattern.

panic and recover are there to help with major faults and stack unwinding, and return codes for detailed error recovery that, frankly, are mechanically ugly to complete without being in the low-level mechanism near the failure.

The convention is "must" will panic if something goes wrong. must really is lowercase here, because one is not to panic across library boundaries.

Uses

Posted Mar 31, 2012 17:00 UTC (Sat) by Cyberax (✭ supporter ✭, #52523) [Link]

Duh. panic/recover is a lame implementation of exceptions. So one certainly can use them for these scenarios.

The problem is, they've squandered opportunity to do something genuinely better, like enforcing the exception safety.

Uses

Posted Mar 31, 2012 22:52 UTC (Sat) by cmccabe (guest, #60281) [Link]

I am going to use some Java terminology here, so bear with me. "Unchecked" exceptions are those that are not required to be caught by anyone. In other words, they are not enforced by the type system. "Checked" exceptions, on the other hand, must be either declared to be thrown by the caller, or handled by the caller.

Unchecked exceptions remove information from the type system, which makes the system less robust, for the same reason using void* and not enforcing invariants does. C++, Python, and many other languages ONLY have unchecked exceptions. In many cases, it's difficult even to get information about what exceptions can be thrown, let alone what to do about them, without reading the entire source code of the function you're calling and all the functions it calls. I've been in this situation before, and it's not pretty. For me at least, this kind of "error handling" is really "error ignoring" since the likelihood that maintenance programmers will know all that stuff approaches zero as time goes on.

Checked exceptions, on the other hand, tend to be just as verbose (and sometimes more verbose) than simple if-then error handling. For example:

try {
  if (is_set(ctx, 'debug_mode') && is_set(ctx,'show_log'))
    do_something();
} catch (IOException e) {
  throw new BlahFailedException("blah failed!  Error: " +
    e.getMessage());
} catch (DoSomethingException e) {
  throw new BlahFailedException("do_something failed!  Error: " +
    e.getMessage());
}
I'm giving you a best-case scenario here-- I didn't have to add a finally block or do something special with RuntimeException, which I often do.

And if you think it's always possible to change your function signature to declare all the checked exceptions you want to throw, think again. For example, if you are implementing an interface like SAXParser or something, you don't get that kind of choice. You'll have to catch and translate every checked exception into either a RuntimeException (which ruins type-safety) or a SAXParseException (which is misleading and verbose to implement).

A final comment. If you design the system such that there are a lot of corner cases are tricky situations, then yes, your code will be tricky. On the other hand, if you design the system such that it's simple, you won't feel the need for complexity. For example, you could load the entire configuration at once and keep it in memory, eliminating the need to handle the "file not found" error condition that you're so worried about. Exceptions don't reduce the complexity of code. At best, they just sweep it under the rug. And that's not a good thing, for anyone concerned.

Another note. In its newest language, Ceylon, Red Hat is getting rid of checked exceptions. Google coding standards for C++ dictate no use of exceptions-- ever. I think the way Go handles exceptions is the right way.

Uses

Posted Mar 31, 2012 23:33 UTC (Sat) by Cyberax (✭ supporter ✭, #52523) [Link]

Well, checked exceptions are a failed idea for many reasons.

First, having an exact exception type in a function signature is BAD. That means that you are expecting these exceptions to be thrown sometime and this means you are most probably better off using return codes in this case.

C++ has a better idea - exception guarantees ( http://en.wikipedia.org/wiki/Exception_guarantees ). I rarely care about types of exceptions but I really care about the fact that exceptions can occur at all. Having a type system enforcing correct exception safety would be really nice.

C++ moves in this direction, but slowly.

>A final comment. If you design the system such that there are a lot of corner cases are tricky situations, then yes, your code will be tricky. On the other hand, if you design the system such that it's simple, you won't feel the need for complexity. For example, you could load the entire configuration at once and keep it in memory, eliminating the need to handle the "file not found" error condition that you're so worried about.

How about lazy-loading of entities from database or memcached? Or maybe a failure to perform action because there's not enough space for audit log entry? There are lots of cases where exceptions can happen.

Callbacks are another case - what happens if a callback encounters an error?

>Exceptions don't reduce the complexity of code. At best, they just sweep it under the rug. And that's not a good thing, for anyone concerned.

Nope. Exceptions help to deal with a thorny problem - non local effects of errors.

>Google coding standards for C++ dictate no use of exceptions-- ever. I think the way Go handles exceptions is the right way.

Google doesn't use exceptions because of legacy. They have a lot of exception-unsafe code and it's just too complex to convert it.

Uses

Posted Apr 1, 2012 2:37 UTC (Sun) by cmccabe (guest, #60281) [Link]

> C++ has a better idea - exception guarantees

You really need to get out of the mentality that C++ is a single thing that "has ideas." Even aside from the obvious anthropomorphism, there is no single person or company that controls the direction of C++. New features are added by a committee. Over the years, an amazing number of features got added. Some of them are useful, some of them are not. Some of them are useful, but interact poorly with other useful features. In the real world, companies choose the subset of features they like the best, and move on.

I programmed C++ for almost 10 years. I've seen a lot of different styles of code in that time. I was once a passionate advocate of exceptions, Boost, and design patterns. My opinions changed a lot when I saw the real-world messes these things made. Reading some of the Golang documents, I found myself agreeing with every point they made. Finally, someone with real-world experience building systems and good taste was designing a successor to C++.

> http://en.wikipedia.org/wiki/Exception_guarantees ). I rarely care about
> types of exceptions but I really care about the fact that exceptions can
> occur at all. Having a type system enforcing correct exception safety
> would be really nice.

The only "guarantees" worth the name are those that are enforced by the compiler. Calling something a "guarantee," when it may or may not be true, is an Orwellian misuse of the language-- like calling a DRM format "PlaysForSure." In my experience, only the best programmers can have even a chance of writing exception-safe code in C++. And even they make mistakes, being human.

> [snip examples]

If it's a programmer error, then panic. If it's anything else, return an appropriate result, whatever that may be.

> Exceptions help to deal with a thorny problem - non local effects
> of errors.

To do proper error handling, you need to clean up local resources. Do exceptions help with that? Nope, it's your job-- even in Java or Python. You need to decide how to handle the problem. Do exceptions help there? Nope. At the end of the day, they are no more than a "goto," whitewashed with a shiny new coat of object-oriented paint.

Uses

Posted Apr 1, 2012 6:41 UTC (Sun) by Cyberax (✭ supporter ✭, #52523) [Link]

Well, I know that C++ doesn't like it when people anthropomorphize it. But it's easier than saying 'some members of C++ committee'.

Golang already shows its ugly areas - people shouldn't allow C developers to design languages. And as I've said, error handling is one of the ugly parts.

I've written a fair amount of code in Go and I've already encountered cases where changes to functions required addition of 'err' parameter, breaking my code in the process.

A some libraries now have all the functions returning Error as the second parameter in all functions, even if it's never actually used but might be used some day in future. Which is crazy.

>The only "guarantees" worth the name are those that are enforced by the compiler.

And that's the plan for the next C++. Even C++11 has noexcept which is already a good step in the right direction ( http://akrzemi1.wordpress.com/2011/06/10/using-noexcept/ ).

Go instead decided to make a step back - it HAS exceptions (a rose by any other name...) but they are fugly.

>If it's a programmer error, then panic. If it's anything else, return an appropriate result, whatever that may be.

That's the result of map.get('something') if map itself misbehaves?

>To do proper error handling, you need to clean up local resources. Do exceptions help with that?

YES, THEY DO!!!

In C++ exception force you to use RAII to manage resources. That ensures that resources are automatically released during the normal execution flow and simply CAN'T be leaked.

While explicit error code handling practically ensures that some cleanup actions are going to be missed. That's why the most common error handling pattern in plain C is 'goto cleanup' which essentially emulates the stack unwinding.

Uses

Posted Apr 1, 2012 23:18 UTC (Sun) by cmccabe (guest, #60281) [Link]

> I've written a fair amount of code in Go and I've already
> encountered cases where changes to functions required
> addition of 'err' parameter, breaking my code in the process.

One of the worst APIs I've used was the original wireless.h (aka "wireless extensions") API in the Linux kernel. Basically, it forwards you a bunch of ioctls that come from userspace. Except it doesn't bother to parse them at all-- it's YOUR job to parse a giant blob of bytes, try to pick out fields, and do pointer-chasing.

When asked why this was so, the author simply replied, "if I had provided a callback API, I would have had to update all the callback implementors each time I added a new field." (I'm paraphrasing a bit; I can't find the original email.) When I read this response, I couldn't stop laughing for about a minute. Well of COURSE you have to change the callback implementors when the ioctl changes. That's the point of the type system! But he couldn't see it. Later wireless.h was replaced by the excellent nl80211 API.

I think, like him, you may be missing the point here. The point of the type system is to make guarantees. Real guarantees, not just conventions. "I will not encounter any errors" is just such a guarantee, and that's what you're promising when you don't provide an error return code.

[snip discussion of noexcept]

C++ already HAS a way of declaring that a function won't throw-- add "throw()" to the end of the function. They're going to add another way?

And apparently this new way will also just be a programmer promise with no real weight:

> This technically allowed the possibility that a noexcept function could
> still throw: this would trigger an undefined behavior. In addition,
> current exception specifications in C++03 were to be deprecated.
>
> Then, Rani Sharoni proposed a different solution... [snip]

Yeah. Sounds like progress. C++ throw specifications are FUBAR, and a change like this will just turn the pain level up to 11. You'll be dealing with two __different__ broken exception specification systems. Good luck dealing with library code that may not get updated to the new system for years!

Even if they managed to sort out this mess, they'd still just be re-inventing Java checked exceptions, which most people find verbose and annoying.

> In C++ exception force you to use RAII to manage resources. That ensures
> that resources are automatically released during the normal execution flow
> and simply CAN'T be leaked.
>
> While explicit error code handling practically ensures that some cleanup
> actions are going to be missed. That's why the most common error handling
> pattern in plain C is 'goto cleanup' which essentially emulates the stack
> unwinding.

Exceptions and RAII are two different things. For example, Google does not use exceptions, but they make heavy use of RAII. Golang also has its own version of RAII, the defer statement. And, of course, garbage collection means that there is a lot less cleanup to do.

Anyway, even Herb Sutter admits that the best exception-safe code which implements a certain algorithm may sometimes be less efficient than the best non-exception-safe code. And he's an enthusiastic advocate of exceptions. So my question to you is, if you're going to sacrifice efficiency in this way, why use a low-level, non-garbage collected, memory-unsafe language in the first place?

Uses

Posted Apr 2, 2012 14:34 UTC (Mon) by jwakely (subscriber, #60262) [Link]

C++ already HAS a way of declaring that a function won't throw-- add "throw()" to the end of the function. They're going to add another way?
A non-empty exception spec i.e. throw(X,Y,Z) is deprecated, but you're left with (as before) throw() meaning the function won't throw or if that's not given then (as before) it means the function might throw, and could throw any type.

But in order to make throw() useful for metaprogramming there's a new way to spell it which is noexcept(true) or simply noexcept. You can also say noexcept(false) to say a function might throw, which seems useless until you realise the boolean can be any constant expression, so a function template with parameter T can be declared noexcept(is_nothrow_copyable<T>::value) i.e. the function guarantees not to throw if copying T won't throw. There is also a noexcept operator that can be used to query whether arbitrary expressions will throw.

It's not a new mechanism, it's the same one with the useless part (non-empty exception specs) removed, and more useful syntax.

If library code isn't updated to the new mechanism it doesn't matter, it still works fine (but noone should be using non-empty exception specs anyway, they're crap) and throw() is equivalent to noexcept.

Uses

Posted Apr 2, 2012 15:00 UTC (Mon) by jwakely (subscriber, #60262) [Link]

(It's not _precisely_ the same, but the differences for most people's uses are equivalent or are an improvement anyway.)

Uses

Posted Mar 30, 2012 0:36 UTC (Fri) by man_ls (subscriber, #15091) [Link]

I don't understand your last paragraph:
Some programmers use recover() to "increase reliability" by catching all possible panics. I find that rather useless, since the whole program will crash if a panic reaches the top of *any goroutine*, and no recover can help. It's usually easier to have a daemon process respawn the program (after logging the crash, of course).
So, can all panics be recovered from, or not? Case in point: I have a Python script which does a complex task and sends an email. If at any point there is an exception, it should also send an email and clean up. Would Go recover() help here?

Uses

Posted Mar 31, 2012 2:08 UTC (Sat) by imgx64 (guest, #78590) [Link]

You can only recover from panics in the same goroutine. If a panic reaches the top of *any goroutine* without being recovered, the whole program crashes, and you can do nothing about it.

Uses

Posted Mar 30, 2012 5:45 UTC (Fri) by Cyberax (✭ supporter ✭, #52523) [Link]

The most common use of exceptions is in the middleware. I.e. you need to start doing something and then undo it in case of exceptions somewhere downstream.

Returning error result more than one level is an anti-pattern. It means that you really need exceptions in this case, since you're starting to emulate them.

And Go isn't an exception. They've just reimplemented exceptions (pun intended) with extra-clumsy syntax to ensure that they're not used by developers. Fail.

Exceptions vs Error Codes

Posted Mar 30, 2012 8:34 UTC (Fri) by ldo (subscriber, #40946) [Link]

Returning error result more than one level is an anti-pattern. It means that you really need exceptions in this case, since you're starting to emulate them.

Or maybe exceptions are the anti-pattern, and returning error codes is a more structured—i.e. refactorable—way of coping with such conditions.

Exceptions vs Error Codes

Posted Mar 30, 2012 9:37 UTC (Fri) by gioele (subscriber, #61675) [Link]

> >Returning error result more than one level is an anti-pattern. It means that you really need exceptions in this case, since you're starting to emulate them.

> Or maybe exceptions are the anti-pattern, and returning error codes is a more structured—i.e. refactorable—way of coping with such conditions.

Well implemented exception systems allow you to transparently handle exceptions up in the stack, not only in the local context that generated them. Instead, if you want to pass up error codes, you will have to manually make sure that every error code is passed as the error code of the current routine and the flow is stopped as soon as an error is detected.

Using error codes also makes it difficult to generate clear and details backtraces, unless your error-reporting routines have a way to write down where the error originally happened and how it has been propagated up in the stack. If you have such facilities then you have implemented an exception systems.

Exceptions vs Error Codes

Posted Mar 30, 2012 10:40 UTC (Fri) by dgm (subscriber, #49227) [Link]

> Well implemented exception systems allow you to transparently handle exceptions up in the stack

If by "transparently" you mean that the code can automatically unwind the stack frames of several unsuspecting functions, you're right. _All_ exceptions systems I know of do this. This is also usually pointed out as one of the weakness in exceptions, because an implicit flow of control is introduced, and you have to always be aware of it. Much like what happens when you write multi-threaded applications.

> if you want to pass up error codes, you will have to manually make sure that every error code is passed as the error code of the current routine and the flow is stopped as soon as an error is detected.

No you don't have to. You can have a global error object (à la errno) and pass up the error _condition_ (that is, that there has been an error). This can even been in the error object, you don't even need to return an special value. What you have to do is check explicitly after each call if there has been an error or not. This is a bug or a feature, depending who you ask. I personally find both useful sometimes, but I have been seen cursing both from time to time. Exceptions are tempting, for the same reason that garbage collection is: it helps you being lazy. But you have to be aware of the price you pay, and that it may come back to bite you later. My personal opinion is that anybody saying one or the other is The Right Thing(TM) is just a moron.

> Using error codes also makes it difficult to generate clear and details backtraces

This is simply not true. There's nothing preventing you from generating backtraces and what not if the language and/or the libraries provide you with the tools (I have done this in Python and Delphi, for instance).

> If you have such facilities then you have implemented an exception systems.

No, because the implicit flow of control that characterizes exceptions is missing.

Exceptions vs Error Codes

Posted Mar 30, 2012 11:56 UTC (Fri) by mgedmin (subscriber, #34497) [Link]

> You can have a global error object (à la errno) and pass up the error _condition_ (that is, that there has been an error).

This pattern is the reason why the Internet is full of screenshots of those "Error: success" dialogs.

Exceptions vs Error Codes

Posted Mar 30, 2012 15:51 UTC (Fri) by khim (subscriber, #9252) [Link]

True. But think about it: just why all these pictures are copied from one resource to another? Because they are rare and thus funny.

On the other hand uncaught exception dumped on the unsuspected user are so common nobody ever tries to ridicule them: it's not funny, it's just sad.

IMNSHO this shows that usually exceptions are not needed and dangerous (just like usually full GC is unneeded and problematic), but some help is welcome. Multiple return values in Go looks like goo 99% compromise. Just as scoped_ptr plus occasional shared_ptr are good compromise WRT GC - to bad Go advocates full GC...

Exceptions vs Error Codes

Posted Mar 30, 2012 18:26 UTC (Fri) by dgm (subscriber, #49227) [Link]

Rather, it's more likely that the cause is using an special code to mean "no error".

Exceptions vs Error Codes

Posted Mar 30, 2012 16:14 UTC (Fri) by nybble41 (subscriber, #55106) [Link]

> If by "transparently" you mean that the code can automatically unwind the stack frames of several unsuspecting functions, you're right. _All_ exceptions systems I know of do this.

IIRC, in Java you have to declare which exceptions a method can raise, including any which might be raised by lower-level functions, unless they are handled internally. So there are no "unsuspecting functions"; the only stack frames which an exception will unwind are those which declared that exception in the prototype. C++ has a similar feature, but it's optional, so it doesn't provide the same guarantees.

Of course, any language which supports non-local returns--including captured continuations and C's setjmp()/longjmp() routines--potentially has the same issue. Exceptions fall somewhere in between, since unlike setjmp() they allow for cleanup in the intermediate stack frames, but unlike continuations they are not (typically) flexible enough to implement arbitrary flow control.

Exceptions vs Error Codes

Posted Mar 30, 2012 16:22 UTC (Fri) by khim (subscriber, #9252) [Link]

So there are no "unsuspecting functions"; the only stack frames which an exception will unwind are those which declared that exception in the prototype.

That's why huge amount of Java code includes empty catch statements. And still RuntimeExceptions blow up programs regularly. I'm not sure if it's even possible to sanely use exceptions, but C#/Java exception handling is disaster.

In my experience exceptions are useless in most cases: sometimes you really want to compartmentalize your program, but fork(2) works fine in such cases. If your task is not large enough to use fork(2) then it's probably not large enough to warrant complex exception-based schemes.

Exceptions vs Error Codes

Posted Mar 30, 2012 19:24 UTC (Fri) by dgm (subscriber, #49227) [Link]

On the other hand, exceptions tend to work nice when you have to repeatedly call library functions that almost always work as intended (that is, errors are really exceptional). In that case you can save a lot of error checking and write simpler code.

Working with exceptions is tricky, but if you know (and follow) the rules it's not more difficult than treads or pointers (:-P)

I will not pretend to know all the rules, but those have served me well:

1. Never, EVER add exceptions to code written without them in mind (this applies basically to C/C++). If you want to use exceptions, do so from day one, or rewrite unaware code.
2. Never, EVER let an uncaught exception escape a callback or event handler. NEVER. And conversely, ALWAYS catch all exceptions when calling back external code or firing events.
3. DON'T use exceptions for common cases or conditions that are easily recoverable. They are best for situations that are truly exceptional and hard to recover from.
4. Program defensively, specially when holding resources (open files, locks, connections, memory). Expect unexpected exceptions everywhere. Your code will probably have a longer and more interesting live than you expect.
5. Handle exceptions ONLY where they make sense. Handling each and every exception everywhere just makes code complex, defeating their purpose. If (when) you find yourself in a mess of try...catches stop and reconsider the exceptions you're using. Do not discard avoiding exceptions altogether.

Ah, just one more thing: don't feed them after midnight. Just don't do it.

Exceptions vs Error Codes

Posted Mar 30, 2012 22:01 UTC (Fri) by khim (subscriber, #9252) [Link]

On the other hand, exceptions tend to work nice when you have to repeatedly call library functions that almost always work as intended (that is, errors are really exceptional). In that case you can save a lot of error checking and write simpler code.

Yup. And as added bonus it'll guarantee your future employment when you'll find and fix dozens of security bugs and DOS cases.

4. Program defensively, specially when holding resources (open files, locks, connections, memory). Expect unexpected exceptions everywhere. Your code will probably have a longer and more interesting live than you expect.

This is what makes exceptions pointless. It's hard enough to find programmers which can correctly programs the common case. Someone who can correctly program all the exceptional codepaths will be usually too expensive. And will still miss some cases.

This is where fork(2) solution saves your beacon: sure, you still need to somehow handle cases where some shared resources (such as pipe or shared memory) misbehaves because other process died but most of the heavy lifting will be done by OS without your direct involvement: sockets will be freed, files will be closed and removed (you do remove temporary files right after open(2) call, because you need to handle poweroff case, right?), etc.

Go is trying to create something like this in a single process - but I'm not 100% sure how well it'll work.

Exceptions vs Error Codes

Posted Mar 30, 2012 23:13 UTC (Fri) by Cyberax (✭ supporter ✭, #52523) [Link]

>This is what makes exceptions pointless. It's hard enough to find programmers which can correctly programs the common case. Someone who can correctly program all the exceptional codepaths will be usually too expensive. And will still miss some cases.

Nope. It's easy in C++ - just wrap everything in RAII-based holders. If you need a cleanup action then wrap it in ON_SCOPE_EXIT macro or make it a lambda function (C++11 is great!). Pretty easy once you get used to it.

On the other hand, meticulously handling return codes just doesn't happen if you don't force it through code reviews.

Exceptions vs Error Codes

Posted Apr 2, 2012 8:02 UTC (Mon) by jezuch (subscriber, #52988) [Link]

> That's why huge amount of Java code includes empty catch statements. And still RuntimeExceptions blow up programs regularly. I'm not sure if it's even possible to sanely use exceptions, but C#/Java exception handling is disaster.

Nope. The reason for this is huge amounts of lazy and clueless programmers. And Java's exceptions are far from being a disaster. I actually love them, despite some wrinkles. There was a time when I submitted to this "exceptions are evil, declare everything as throwing Throwable" movement and I regretted this ever since. I'm also reminded of this every time I have to code something in C and error handling becomes a chore and pain even worse than manual memory management ;)

Exceptions vs Error Codes

Posted Mar 30, 2012 19:22 UTC (Fri) by Cyberax (✭ supporter ✭, #52523) [Link]

Error codes? Refactorable? LOL!

Error codes are among the worst inventions, and cause no end of problems during refactoring. What should you function return if underlying function fails with FILE_NOT_FOUND error?

Should you just pass it through or maybe you should just invent your own exit codes? What about additional information (you know, a user might want to know the name of the file that has not been found)? Should we store it in a thread-local variable? Hm. Who is going to release it when it's not needed?

And what about compounded errors, i.e. we want to know how NAIL_NOT_FOUND caused THE_KINGDOM_WAS_LOST error? We might want a stacktrace!

And when you solve all these problems you'll get exceptions. Except they probably will be badly implemented.

Uses

Posted Mar 29, 2012 0:28 UTC (Thu) by fdr (subscriber, #57064) [Link]

It's much more C-ish than C++, and scales down much better than plain C (the big one is garbage collection). It probably scales up about the same, or better.

Having written quite a bit of C, and a bit of Go (I sit next to a couple of Go aficionados) I'm inclined to like it, and I think it'll be a pleasure to use for most C hackers who are just slightly above the lowest levels of bit-twiddling and register-mangling, but need to carefully consider memory allocations and layout.

Uses

Posted Mar 29, 2012 16:44 UTC (Thu) by b7j0c (subscriber, #27559) [Link]

anywhere you would use python or java

Uses

Posted Mar 29, 2012 22:37 UTC (Thu) by k8to (subscriber, #15413) [Link]

Sounds nice for projects where I currently use python as a proxy for libc APIs. Which is a lot of scut code or test code.

Sounds bad for projects where I lean heavily on dynamic behavior to simplify logic, so here I would keep using Python.

Uses

Posted Mar 30, 2012 1:39 UTC (Fri) by kjp (subscriber, #39639) [Link]

Nothing. Because I already use c++, objective c (which has some good ideas too), and python, and this doesn't seem to have any killer feature worth the learning cost.

Well, perhaps if the python GIL is causing pain I would look at GO more closely.. in which case it also would be compared against Java and C++.

As far as "channels", I do that already with pipes and multiple processes and get fault isolation to boot. As far as 'fast compile speed', that's because you're not inlining anywhere near what c++ does.

Copyright © 2013, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds