Discussion:
Go Error Handling Sucks
k***@public.gmane.org
2012-09-24 15:55:57 UTC
Permalink
Its a shame that such a fantastic language is missing a better way to deal
with errors.
Exceptions might not be perfect, but are damn better than checking each and
every function call.

Or am I missing something?

I just read a pair of posts that expresses these ideas much better than
what I could here.

http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/

http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html

As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.

--
Aram Hăvărneanu
2012-09-24 18:04:55 UTC
Permalink
.-'\
.-' `/\
.-' `/\
\ `/\
\ `/\
\ _- `/\ _.--.
\ _- `/`-..--\ )
\ _- `,',' / ,')
`-_ - ` -- ~ ,','
`- ,','
\,--. ____==-~
\ \_-~\
`_-~_.-'
\-~
--
Aram Hăvărneanu

--
Gustavo Niemeyer
2012-09-24 18:35:33 UTC
Permalink
FWIW, I find that unnecessarily unfriendly. This is a pretty common
issue people perceive when coming to the language, and it's to me one
of the great benefits of Go too. This is a user mailing list, so I
suggest we try to welcome people with those kinds of questions with
proper feedback, as done by others here, rather incorrectly suggesting
no one cares.

To the OP, if you're considering Python vs. Go, here are a handful of
posts to get you thinking.

Curiously, many of them were written before I switched to Go.

http://blog.labix.org/2009/05/15/class-member-access-control-enforcement-vs-convention
http://blog.labix.org/2009/07/02/screwing-up-python-compatibility-unicode-str-bytes
http://blog.labix.org/2010/06/17/the-forgotten-art-of-error-checking
http://blog.labix.org/2010/07/09/python-has-a-gil-and-lots-of-complainers
http://blog.labix.org/2010/11/09/interfaces-and-the-design-of-software
http://blog.labix.org/2011/12/12/good-concurrency-changes-the-game
http://blog.labix.org/2012/06/26/less-is-more-and-is-not-always-straightforward
Post by Aram Hăvărneanu
.-'\
.-' `/\
.-' `/\
\ `/\
\ `/\
\ _- `/\ _.--.
\ _- `/`-..--\ )
\ _- `,',' / ,')
`-_ - ` -- ~ ,','
`- ,','
\,--. ____==-~
\ \_-~\
`_-~_.-'
\-~
--
Aram Hăvărneanu
--
--
gustavo @ http://niemeyer.net

--
Andrew Gerrand
2012-09-24 19:27:01 UTC
Permalink
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=google.com; s=20120113;
h=x-beenthere:received-spf:mime-version:sender:in-reply-to:references
:from:date:message-id:subject:to:cc:x-system-of-record
:x-gm-message-state:x-original-sender
:x-original-authentication-results:precedence:mailing-list:list-id
:x-google-group-id:list-post:list-help:list-archive:list-subscribe
:list-unsubscribe:content-type;
bh=SKM9i1OlFKPlXWfuNwEEk89lSrPtkRSUgx5pRLYd4NM=;
b=S+Wy3B6fOsxZhX8BHaW45aRMZVmSw/CuKfrqwTucRXPBW85UpQ9wrksOKUqHgeFo02
E5xvZBSPOYe6ts0si5TF/mPXXW8AAbgxtrTPq9ACKbSu4LhvJj5Z/R/co1Cw1jSww6Fw
y7metEYajbgOQHU/O5bYdSGCJDk1piB8DiHV5kArdV8d73wnV34bo38a6JFK60+xiAqG
Rn97gsOXolgpm13/Iaqp9Z464T1Cg91tuG7irC3L2P8EdUNZskpm6gw9yBWoaTZiImTm
vRwZMEWdCc2nBOCqASUFhOkeAg005g1pjSK9ZkQ2x0Sb
Received: by 10.236.139.196 with SMTP id c44mr1776842yhj.17.1348514855695;
Mon, 24 Sep 2012 12:27:35 -0700 (PDT)
X-BeenThere: golang-nuts-/***@public.gmane.org
Received: by 10.236.120.244 with SMTP id p80ls9809423yhh.0.gmail; Mon, 24 Sep
2012 12:27:33 -0700 (PDT)
Received: by 10.236.141.237 with SMTP id g73mr735588yhj.12.1348514853137;
Mon, 24 Sep 2012 12:27:33 -0700 (PDT)
Received: by 10.236.141.237 with SMTP id g73mr735587yhj.12.1348514853126;
Mon, 24 Sep 2012 12:27:33 -0700 (PDT)
Received: from mail-qc0-f175.google.com (mail-qc0-f175.google.com [209.85.216.175])
by gmr-mx.google.com with ESMTPS id g28si5398553qcq.2.2012.09.24.12.27.32
(version=TLSv1/SSLv3 cipher=OTHER);
Mon, 24 Sep 2012 12:27:32 -0700 (PDT)
Received-SPF: pass (google.com: domain of adg-hpIqsD4AKlfQT0dZR+***@public.gmane.org designates 209.85.216.175 as permitted sender) client-ip=209.85.216.175;
Received: by mail-qc0-f175.google.com with SMTP id d10so5184678qca.20
for <golang-nuts-/***@public.gmane.org>; Mon, 24 Sep 2012 12:27:32 -0700 (PDT)
Received: by 10.224.97.197 with SMTP id m5mr34289665qan.57.1348514851999;
Mon, 24 Sep 2012 12:27:31 -0700 (PDT)
Received: by 10.224.97.197 with SMTP id m5mr34289643qan.57.1348514851898; Mon,
24 Sep 2012 12:27:31 -0700 (PDT)
Sender: golang-nuts-/***@public.gmane.org
Received: by 10.224.174.212 with HTTP; Mon, 24 Sep 2012 12:27:01 -0700 (PDT)
In-Reply-To: <CANySw1nGq=AEr=nAbmF=GxKE=LAEa3Z37T2H9NzekUMquDj3hw-JsoAwUIsXosN+***@public.gmane.org>
X-System-Of-Record: true
X-Gm-Message-State: ALoCoQn+jpbdWMLC7FADop9k1JFVwsDPADJ0tsAtcemCjUrad3Y/TVNHDPvCcNz+6juNnD6ity4NT2KK2Co4/t0/B5bRGTcdSSXIlzmvyPA56Sz16+sUp1loJvNnjSn2k2Q+lXqf5emWDiJCD/1g1ZMshbfcxjcn99Xsh8Td07Qv+i5HJaPWRVyrHSNBnIbEQ2OLLq+lvkRxFs+e6aHWd/Gv5VHAJm83Mg==
X-Original-Sender: adg-hpIqsD4AKlfQT0dZR+***@public.gmane.org
X-Original-Authentication-Results: gmr-mx.google.com; spf=pass (google.com:
domain of adg-hpIqsD4AKlfQT0dZR+***@public.gmane.org designates 209.85.216.175 as permitted sender)
smtp.mail=adg-hpIqsD4AKlfQT0dZR+***@public.gmane.org; dkim=pass header.i=@google.com
Precedence: list
Mailing-list: list golang-nuts-/***@public.gmane.org; contact golang-nuts+owners-/***@public.gmane.org
List-ID: <golang-nuts.googlegroups.com>
X-Google-Group-Id: 332403668183
List-Post: <http://groups.google.com/group/golang-nuts/post?hl=en-US>, <mailto:golang-nuts-/***@public.gmane.org>
List-Help: <http://groups.google.com/support/?hl=en-US>, <mailto:golang-nuts+help-/***@public.gmane.org>
List-Archive: <http://groups.google.com/group/golang-nuts?hl=en-US>
List-Subscribe: <http://groups.google.com/group/golang-nuts/subscribe?hl=en-US>,
<mailto:golang-nuts+subscribe-/***@public.gmane.org>
List-Unsubscribe: <http://groups.google.com/group/golang-nuts/subscribe?hl=en-US>,
<mailto:googlegroups-manage+332403668183+unsubscribe-/***@public.gmane.org>
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.go.general/72271>

There is some discussion of error handling in this talk, Go in Production:


Andrew

--
Robert Johnstone
2012-09-25 21:50:25 UTC
Permalink
+1

--
Dave Cheney
2012-09-24 18:06:21 UTC
Permalink
Hello,

If we are trading links, allow me to quote myself.

http://dave.cheney.net/2012/01/18/why-go-gets-exceptions-right

I hope you do not dismiss Go so quickly. If you spend some time using the
language, rather than being lead around by the great unwashed on reddit,
you may have an opportunity to change your mind.

Dave
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to deal
with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
--
k***@public.gmane.org
2012-09-24 20:52:58 UTC
Permalink
@Dave Cheney Good article explaining the pros/cons of each .... but still
unconvinced. I'm still partial to un-checked exceptions despite the issues
that you point out.
Post by Dave Cheney
Hello,
If we are trading links, allow me to quote myself.
http://dave.cheney.net/2012/01/18/why-go-gets-exceptions-right
I hope you do not dismiss Go so quickly. If you spend some time using the
language, rather than being lead around by the great unwashed on reddit,
you may have an opportunity to change your mind.
Dave
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
--
Gustavo Niemeyer
2012-09-24 21:17:21 UTC
Permalink
Post by k***@public.gmane.org
@Dave Cheney Good article explaining the pros/cons of each .... but still
unconvinced. I'm still partial to un-checked exceptions despite the issues
that you point out.
I think people are eagerly trying to show you a different perspective,
rather than simply attempting to convince you of anything. I
appreciate the conventions in Go because I have to write software that
doesn't crash, even when I'm not looking, not because someone tried to
convince me.


gustavo @ http://niemeyer.net

--
Harley Laue
2012-09-24 22:06:24 UTC
Permalink
Well, in C++ take the following code:
#include <stdexcept>
#include <iostream>
#include <cstdlib>

void C() {
throw std::runtime_error("Let someone else deal with it");
}

void B() {
C();
throw std::runtime_error("Let someone else deal with it");
}

void A() {
try {
B();
}
// A not to uncommon exception catch-all
catch(std::exception &e) {
std::cout << "Unacceptable error: " << e.what() << std::endl;
throw;
}
}

int main(int argc, char *argv[]) {
A();
}

With this simple example, it's pretty easy to see where the exception
is being thrown, but add 50+ lines of code and things become less
clear that B was lazy and just let A deal with C's exception. The
stack trace is going to lead you to A, but from there, you'll have to
hunt as to what actually threw the error because B didn't handle C's
exception when it called it because "it's someone elses problem." This
type of situation actually comes up more frequently than it should.

*shrugs* It's really up to you though to give it a try, decide if you
like Go's method or not. As others have said, it does tend to cause
programs to have less issues because errors are either dealt with, or
they were ignored leading to issues down the road.
Post by k***@public.gmane.org
@Dave Cheney Good article explaining the pros/cons of each .... but still
unconvinced. I'm still partial to un-checked exceptions despite the issues
that you point out.
Post by Dave Cheney
Hello,
If we are trading links, allow me to quote myself.
http://dave.cheney.net/2012/01/18/why-go-gets-exceptions-right
I hope you do not dismiss Go so quickly. If you spend some time using the
language, rather than being lead around by the great unwashed on reddit, you
may have an opportunity to change your mind.
Dave
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
--
--
Jan Mercl
2012-09-24 18:09:31 UTC
Permalink
message, end of the story. I don't want to check every freaking single
function invocation for errors.
Most programmers don't want to. No wonder so much code fails so often.
Its a shame, I really wanted to use go.
You might like Go if you give it a try.

-j

--
Patrick Mylund Nielsen
2012-09-24 18:10:02 UTC
Permalink
Go has exceptions (panic/recover) if you insist on doing it that way. Just
don't expose the users of your APIs to un-exceptional panics (panics
stemming from things other than bad input/incorrect use.)

As others mentioned, you need to use Go. Saying "It's a shame, I really
wanted to use Go" without ever even touching Go is just cheating yourself
out of using a great language.
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to deal
with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
--
Archos
2012-09-24 18:16:34 UTC
Permalink
The language I used before of Go was Python, so the error handling in Go
was very strange for me at the beginning. In fact, one of the errors that I
have done in one of my first projects was to avoid its usage on the first
version, because when I started to extend that project I got errors that I
didn't know where they came from.

So, my rule is always to handle errors since it does not hurts but does
very robust the software.
By the way, now I want not know anymore about Python, Ruby, C++
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to deal
with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
Steven Rice
2012-09-24 18:18:45 UTC
Permalink
On the contrary, Go error handling is amazing. It actually is built
originally to have programmers code responsibly but now panic and recover
have been added for those who wish to do things quick and messily.
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to deal
with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
Rémy Oudompheng
2012-09-24 18:22:31 UTC
Permalink
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to deal
with errors.
Exceptions might not be perfect, but are damn better than checking each and
every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than what
I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the happy
path and if something breaks in the middle the error handling is exactly the
same: log the error, close resources, send the caller an error code or
message, end of the story. I don't want to check every freaking single
function invocation for errors.
Its a shame, I really wanted to use go.
This is a very common misconception which I think should enter the FAQ
or be the subject of a blog article integrated with the Go
documentation.

* "Go error handling sucks" is an inaccurate judgement. Error handling
is not done by Go but written by you.
If your error handling is ugly (which may happen), there are various
things you can do to help that.

* Have your functions return less errors. Errors happen when your
validate external input or perform I/O with other systems. Internal
computations should not generate errors unless you are misusing the
type system (e.g. passing potentially invalid
strings/interface/map[string]interface everywhere instead of
structured data), or in need of pre/post-conditions that cannot be
expressed in Go's type systems (then if the error is a programming
error, it is common to panic rather than return an error).

* Use higher level functions. If you call 42 functions in a row and
check errors 42 times, yes the code is repetitive and ugly, but it's
not because Go is badly conceived. It's either because you have
unrolled operations that could have been gathered in more friendly
ways, either because the operation is genuinely complicated, in which
case a careful handling of errors is needed.

* Errors are messages. They are not stack traces, they are not
stringified exception contents taken out of their context. A 50-line
Java stacktrace is not something you can show to an end-user. If you
don't care about the user and prefer raw stacktraces, it might be
because you are scripting. Then you can use panic in Go or Python,
because you don't want to bother about proper error handling.
Identifying the location of an error, its root cause or its context
requires human interaction or a powerful natural language algorithm.
When you talk to human beings (I mean, not programmers), replacing a
stack trace by a helpful sentence that help both end user and
programmer for bug reports is a delicate art. Requiring users to run a
gdb session is not an option.

Websites errors that say "We have encountered an error, sorry for your
request" because stack traces are "security breaches" (that's what
they think at Django's, I've heard), are unhelpful ("yes, I clearly
see you have a problem") and disrespectful to the end-user.

Rémy.

--
Hasen el Judy
2012-09-24 21:50:03 UTC
Permalink
This! It's one of the big benefits of Go's style of error handling

If you craft the error message in a way that's meaningful to the user, you
can seamlessly report errors to the end-user as-is.

I've actually been doing that without realizing it. It just comes naturally
when you realize that an error is just a string and you can report it to
the user directly.
Post by Rémy Oudompheng
* Errors are messages. They are not stack traces, they are not
stringified exception contents taken out of their context. A 50-line
Java stacktrace is not something you can show to an end-user. If you
don't care about the user and prefer raw stacktraces, it might be
because you are scripting. Then you can use panic in Go or Python,
because you don't want to bother about proper error handling.
Identifying the location of an error, its root cause or its context
requires human interaction or a powerful natural language algorithm.
When you talk to human beings (I mean, not programmers), replacing a
stack trace by a helpful sentence that help both end user and
programmer for bug reports is a delicate art. Requiring users to run a
gdb session is not an option.
Websites errors that say "We have encountered an error, sorry for your
request" because stack traces are "security breaches" (that's what
they think at Django's, I've heard), are unhelpful ("yes, I clearly
see you have a problem") and disrespectful to the end-user.
Rémy.
--
Patrick Mylund Nielsen
2012-09-24 22:45:59 UTC
Permalink
100% agree with your first four points.
Websites errors that say "We have encountered an error, sorry for your request"
because stack traces are "security breaches" (that's what they think at
Django's, I've heard), are unhelpful ("yes, I clearly see you have a
problem") and disrespectful to the end-user.

They DO pose security concerns, and to comment on your specific example,
Django includes much, much more than just a stack trace in its development
mode exception view (like file paths and other configuration options.) I
don't know if "at Django's" is supposed to be an insult, but this is a
pretty fundamental rule in cryptography: don't reveal internal state on
errors, and especially don't try to continue the session; just cut the
connection/session.

There is no reason that you shouldn't tell your user what field of a form
they entered incorrectly, but there also isn't any reason whatsoever that
you should dump e.g. a web application's state to the page when an
unexpected error is encountered. I think you are arguing against yourself a
bit here: as you said, 99% of users don't care about, or won't read your
stack traces, so why should you give them one if they encounter an unknown
error on your site?

net/http handles this correctly: a panic in a request goroutine aborts a
response, and the panic is recovered, letting the http server continue. If
you handle error return values, you have an opportunity to render the error
message nicely, assuming that that error is one you want to show (probably
don't want an "Failed to connect to PostgreSQL database; connection string
"user=foo password=bar..." output on the page.

There's no reason you can't do the same in Django, it's just a lot harder
since handling a lot of different possible exceptions and adding
descriptions for them is much clumsier, like you describe.

On Mon, Sep 24, 2012 at 1:22 PM, Rémy Oudompheng
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal
Post by k***@public.gmane.org
with errors.
Exceptions might not be perfect, but are damn better than checking each
and
Post by k***@public.gmane.org
every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what
Post by k***@public.gmane.org
I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
Post by k***@public.gmane.org
As one of the comments I read said: 99% of the time I need to code the
happy
Post by k***@public.gmane.org
path and if something breaks in the middle the error handling is exactly
the
Post by k***@public.gmane.org
same: log the error, close resources, send the caller an error code or
message, end of the story. I don't want to check every freaking single
function invocation for errors.
Its a shame, I really wanted to use go.
This is a very common misconception which I think should enter the FAQ
or be the subject of a blog article integrated with the Go
documentation.
* "Go error handling sucks" is an inaccurate judgement. Error handling
is not done by Go but written by you.
If your error handling is ugly (which may happen), there are various
things you can do to help that.
* Have your functions return less errors. Errors happen when your
validate external input or perform I/O with other systems. Internal
computations should not generate errors unless you are misusing the
type system (e.g. passing potentially invalid
strings/interface/map[string]interface everywhere instead of
structured data), or in need of pre/post-conditions that cannot be
expressed in Go's type systems (then if the error is a programming
error, it is common to panic rather than return an error).
* Use higher level functions. If you call 42 functions in a row and
check errors 42 times, yes the code is repetitive and ugly, but it's
not because Go is badly conceived. It's either because you have
unrolled operations that could have been gathered in more friendly
ways, either because the operation is genuinely complicated, in which
case a careful handling of errors is needed.
* Errors are messages. They are not stack traces, they are not
stringified exception contents taken out of their context. A 50-line
Java stacktrace is not something you can show to an end-user. If you
don't care about the user and prefer raw stacktraces, it might be
because you are scripting. Then you can use panic in Go or Python,
because you don't want to bother about proper error handling.
Identifying the location of an error, its root cause or its context
requires human interaction or a powerful natural language algorithm.
When you talk to human beings (I mean, not programmers), replacing a
stack trace by a helpful sentence that help both end user and
programmer for bug reports is a delicate art. Requiring users to run a
gdb session is not an option.
Websites errors that say "We have encountered an error, sorry for your
request" because stack traces are "security breaches" (that's what
they think at Django's, I've heard), are unhelpful ("yes, I clearly
see you have a problem") and disrespectful to the end-user.
Rémy.
--
--
Rémy Oudompheng
2012-09-24 23:12:36 UTC
Permalink
Post by Patrick Mylund Nielsen
They DO pose security concerns, and to comment on your specific example,
Django includes much, much more than just a stack trace in its development
mode exception view (like file paths and other configuration options.) I
don't know if "at Django's" is supposed to be an insult, but this is a
pretty fundamental rule in cryptography: don't reveal internal state on
errors, and especially don't try to continue the session; just cut the
connection/session.
There is no reason that you shouldn't tell your user what field of a form
they entered incorrectly, but there also isn't any reason whatsoever that
you should dump e.g. a web application's state to the page when an
unexpected error is encountered. I think you are arguing against yourself a
bit here: as you said, 99% of users don't care about, or won't read your
stack traces, so why should you give them one if they encounter an unknown
error on your site?
My point was that, in languages that encourage you to use exceptions,
when an exception occur that is not handled (due to an overlook or
whatever), the framework doesn't have anything else than a stack trace
or internal state to describe the error, and since there is nothing
interesting to do, it doesn't show a useful error.

This doesn't happen in languages that encourage you to check all errors.

Rémy.

--
Patrick Mylund Nielsen
2012-09-24 23:14:16 UTC
Permalink
Ah, then I agree :) Nothing to see here.

On Mon, Sep 24, 2012 at 6:12 PM, Rémy Oudompheng
Post by Patrick Mylund Nielsen
Post by Patrick Mylund Nielsen
They DO pose security concerns, and to comment on your specific example,
Django includes much, much more than just a stack trace in its
development
Post by Patrick Mylund Nielsen
mode exception view (like file paths and other configuration options.) I
don't know if "at Django's" is supposed to be an insult, but this is a
pretty fundamental rule in cryptography: don't reveal internal state on
errors, and especially don't try to continue the session; just cut the
connection/session.
There is no reason that you shouldn't tell your user what field of a form
they entered incorrectly, but there also isn't any reason whatsoever that
you should dump e.g. a web application's state to the page when an
unexpected error is encountered. I think you are arguing against
yourself a
Post by Patrick Mylund Nielsen
bit here: as you said, 99% of users don't care about, or won't read your
stack traces, so why should you give them one if they encounter an
unknown
Post by Patrick Mylund Nielsen
error on your site?
My point was that, in languages that encourage you to use exceptions,
when an exception occur that is not handled (due to an overlook or
whatever), the framework doesn't have anything else than a stack trace
or internal state to describe the error, and since there is nothing
interesting to do, it doesn't show a useful error.
This doesn't happen in languages that encourage you to check all errors.
Rémy.
--
Steven Johnson
2012-09-24 19:05:24 UTC
Permalink
Its a shame that such a fantastic language is missing a better way to deal with errors.
Exceptions might not be perfect, but are damn better than checking each and every function call.
There's no accounting for taste, I guess -- IMHO the Go error checking
style is one of the things I find to be a big benefit of the language.
There's no hidden control flow; error conditions are in your face and
you have to make a deliberate decision to ignore them (thanks to the
no-warning, no-unused-declarations compiler).

(OK, technically panic/recover are "hidden control flow", but they're
really only for use after the ship has already hit the iceberg, so to
speak...)

--
DisposaBoy
2012-09-24 19:47:22 UTC
Permalink
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to deal
with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
Form what you've said, it doesn't appear that you are able to form your own
opinions. What happens if I tell you that it's a good idea to go jumping
off bridges? ... In any case, please don't spam the list




--
k***@public.gmane.org
2012-09-24 23:35:42 UTC
Permalink
@DisposaBoy I do have my opinions, I just pointed to a blog that summed it
up quite nicely. If you tell me to jump of a bridge, I will probably push
you off instead. You are the one spamming the list with your reply devoid
of content. As you can see, there has been quite some interest in my
sololoquy.
Post by DisposaBoy
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
Form what you've said, it doesn't appear that you are able to form your
own opinions. What happens if I tell you that it's a good idea to go
jumping off bridges? ... In any case, please don't spam the list
--
Patrick Mylund Nielsen
2012-09-24 23:52:01 UTC
Permalink
What DisposaBoy was pointing out is that your original post basically read,
"Your error handling sucks! Some other guys said that your error handling
sucks. Why does it suck? Too bad, now I won't use your language", and it
was obvious that you haven't actually used the language yourself. You need
to use the language, or at least study (more) code written in it, before
you adopt and parrot somebody else's opinion, especially if you're going to
post such a condescending/derisive message to that language's mailing list.

Of course, that doesn't just apply to programming languages. Many
programmers use NoSQL databases to be able to make "web scale"
applications, and not RDBMS, even though they will likely be tens or
hundreds of times as productive using something relational, and won't
actually have the problems that Facebook has for messaging (they still use
MySQL for everything else)--and one of the major reasons they're using
these solutions is that Hacker News and reddit.com/r/programming are filled
with threads that worship the latest new thing and dismisses RDBMSs as "old
and bad" (when in reality they're some of the most mature pieces of
software that exist.) Now that Google has unveiled Spanner, maybe all the
programmers who made MongoDB applications will rave about ACID,
transactional consistency and the ease-of-use of query languages... :) (It
already exists I guess: "NewSQL".)

My/our point is: Don't dismiss something because someone got to #1 on
Hacker News criticizing it. In a lot of cases, they don't really know what
they're talking about, so adopting their (misinformed) opinion is doing
yourself a disfavor. NoSQL, or exceptions, may be right for you, but that
may be the case far less often than you'd think if you ingest Hacker News
articles uncritically. Try it, then make up your own mind.
Post by k***@public.gmane.org
@DisposaBoy I do have my opinions, I just pointed to a blog that summed
it up quite nicely. If you tell me to jump of a bridge, I will probably
push you off instead. You are the one spamming the list with your reply
devoid of content. As you can see, there has been quite some interest in
my sololoquy.
Post by DisposaBoy
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.**com/2012/09/23/why-im-not-**
leaving-python-for-go/<http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/>
http://www.yosefk.com/blog/**error-codes-vs-exceptions-**
critical-code-vs-typical-code.**html<http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html>
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
Form what you've said, it doesn't appear that you are able to form your
own opinions. What happens if I tell you that it's a good idea to go
jumping off bridges? ... In any case, please don't spam the list
--
--
Michael Jones
2012-09-25 00:51:26 UTC
Permalink
One positive point about exceptions: it is nice to have the "happy case"
code flow be clean. I perform a mental code folding around the expected
outcomes when reading. Sometimes my inability to do this influences my
design so that it can work out that way. In a perfect world it would be
great to have both:

* Error handling right at the point of return so that you can see what is
handled or not handled, how it is handled, and what types of failures are
possible.

* Error handling somewhere else so that the logic of the algorithm is
expressed purely and not obscured by a crowd of real-world constraints and
possibile woes.

Clearly a compromise is to be expected and as Dave Cheney's article
explains, the issue is about where and how to implement out-of-band
signaling. There are only so many choices and most of them have been tried
by a number of programming languages. (Though some may not be familiar with
many of those explorations.) There may be new ways, but if the choice is
between too mysterious and too explicit then I prefer Go's explicit
handling at the point of return (which is also the point of call in most
languages ;-)

If I can have new and possibly complicated language features, I might be
tempted to support something that helps with information hiding in cases
where the error handling feels redundant and bulky compared to the
underlying code.

One wonderful example of this kind of outcome is Go's defer, which factors
the proper handling of cases out of each leaf of the code path. Imagine an
error handling version along similar lines. I'll describe it here not as a
proposal, but as an unpolished but hopefully clear way to make my meaning
plain.

Imagine a magic kind of active variable where assigning non-zero to it
stored a value and also (hold your booing) caused an implicit goto. Now,
imagine that we used such a mechanism to implement something like this:

:
resultA, active := functionA( ... )
:
resultB, active := functionB( ... )
:

handle active {
case memoryError:
:
case diskExploded:
:
case alienInvasion:
Panic
}

This kind of thing (just a quick example at 5am in a hotel in Delhi, be
gentle with me) would allow one to "hide" the handling somewhere else when
useful, would let developers factor a number of "out of same resource and
share the same action" cases with one block of handling code, and do much
of what exceptions do magically via the stack in a visible way using the
multiple return value and a jump based on assigned data. In practice, the
active variable could just be named "handle" and the handle kind of switch
could use the implicit handle value. They could nest, maybe, or have labels
or whatnot. My point is not to suggest how to do it but to share that there
are virtues in exceptions that have nothing to do with the actual exception
mechanism, how they work in other languages, how they have been cruelly
overused, and so on.

Michael

P.S. knotwelkum, your observations are welcome by me.

On Tue, Sep 25, 2012 at 5:22 AM, Patrick Mylund Nielsen <
Post by Patrick Mylund Nielsen
What DisposaBoy was pointing out is that your original post basically
read, "Your error handling sucks! Some other guys said that your error
handling sucks. Why does it suck? Too bad, now I won't use your language",
and it was obvious that you haven't actually used the language yourself.
You need to use the language, or at least study (more) code written in it,
before you adopt and parrot somebody else's opinion, especially if you're
going to post such a condescending/derisive message to that language's
mailing list.
Of course, that doesn't just apply to programming languages. Many
programmers use NoSQL databases to be able to make "web scale"
applications, and not RDBMS, even though they will likely be tens or
hundreds of times as productive using something relational, and won't
actually have the problems that Facebook has for messaging (they still use
MySQL for everything else)--and one of the major reasons they're using
these solutions is that Hacker News and reddit.com/r/programming are
filled with threads that worship the latest new thing and dismisses RDBMSs
as "old and bad" (when in reality they're some of the most mature pieces of
software that exist.) Now that Google has unveiled Spanner, maybe all the
programmers who made MongoDB applications will rave about ACID,
transactional consistency and the ease-of-use of query languages... :) (It
already exists I guess: "NewSQL".)
My/our point is: Don't dismiss something because someone got to #1 on
Hacker News criticizing it. In a lot of cases, they don't really know what
they're talking about, so adopting their (misinformed) opinion is doing
yourself a disfavor. NoSQL, or exceptions, may be right for you, but that
may be the case far less often than you'd think if you ingest Hacker News
articles uncritically. Try it, then make up your own mind.
Post by k***@public.gmane.org
@DisposaBoy I do have my opinions, I just pointed to a blog that summed
it up quite nicely. If you tell me to jump of a bridge, I will probably
push you off instead. You are the one spamming the list with your reply
devoid of content. As you can see, there has been quite some interest in
my sololoquy.
Post by DisposaBoy
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.**com/2012/09/23/why-im-not-**
leaving-python-for-go/<http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/>
http://www.yosefk.com/blog/**error-codes-vs-exceptions-**
critical-code-vs-typical-code.**html<http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html>
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
Form what you've said, it doesn't appear that you are able to form your
own opinions. What happens if I tell you that it's a good idea to go
jumping off bridges? ... In any case, please don't spam the list
--
--
--
Michael T. Jones | Chief Technology Advocate | mtj-hpIqsD4AKlfQT0dZR+***@public.gmane.org | +1
650-335-5765

--
Patrick Mylund Nielsen
2012-09-25 01:15:05 UTC
Permalink
FWIW I didn't mean to imply that exceptions are bad--perhaps the comparison
to NoSQL hype was unfair :)--just that error return values aren't. The code
may be harder to skim (although I think it's something you get used to),
but it leads to code that is more "naturally" robust, and, as a side
effect, error messages that are much more specific (as Remy mentioned.)

Look at a language like Haskell: they have the Maybe and Either data
types--Maybe a is a value that may be Just a or Nothing, and Either a b is
a value that may be Left a (where a is usually an error type) or Right b
(where b is some thing), but they also have Python-esque exceptions. Sound
familiar? (On that note, Haskell actually has several more ways to do error
handling, and they've been debating how to solve that so as to not have
varying error handling techniques across packages (which means package
authors can't anticipate what kinds of errors they need to handle)--
http://www.randomhacks.net/articles/2007/03/10/haskell-8-ways-to-report-errors
/ http://article.gmane.org/gmane.comp.lang.haskell.libraries/6382. Go
strikes a nice balance, IMO, between Either and "awkward exceptions"
(panic/recover.)
Post by Michael Jones
One positive point about exceptions: it is nice to have the "happy case"
code flow be clean. I perform a mental code folding around the expected
outcomes when reading. Sometimes my inability to do this influences my
design so that it can work out that way. In a perfect world it would be
* Error handling right at the point of return so that you can see what is
handled or not handled, how it is handled, and what types of failures are
possible.
* Error handling somewhere else so that the logic of the algorithm is
expressed purely and not obscured by a crowd of real-world constraints and
possibile woes.
Clearly a compromise is to be expected and as Dave Cheney's article
explains, the issue is about where and how to implement out-of-band
signaling. There are only so many choices and most of them have been tried
by a number of programming languages. (Though some may not be familiar with
many of those explorations.) There may be new ways, but if the choice is
between too mysterious and too explicit then I prefer Go's explicit
handling at the point of return (which is also the point of call in most
languages ;-)
If I can have new and possibly complicated language features, I might be
tempted to support something that helps with information hiding in cases
where the error handling feels redundant and bulky compared to the
underlying code.
One wonderful example of this kind of outcome is Go's defer, which factors
the proper handling of cases out of each leaf of the code path. Imagine an
error handling version along similar lines. I'll describe it here not as a
proposal, but as an unpolished but hopefully clear way to make my meaning
plain.
Imagine a magic kind of active variable where assigning non-zero to it
stored a value and also (hold your booing) caused an implicit goto. Now,
resultA, active := functionA( ... )
resultB, active := functionB( ... )
handle active {
Panic
}
This kind of thing (just a quick example at 5am in a hotel in Delhi, be
gentle with me) would allow one to "hide" the handling somewhere else when
useful, would let developers factor a number of "out of same resource and
share the same action" cases with one block of handling code, and do much
of what exceptions do magically via the stack in a visible way using the
multiple return value and a jump based on assigned data. In practice, the
active variable could just be named "handle" and the handle kind of switch
could use the implicit handle value. They could nest, maybe, or have labels
or whatnot. My point is not to suggest how to do it but to share that there
are virtues in exceptions that have nothing to do with the actual exception
mechanism, how they work in other languages, how they have been cruelly
overused, and so on.
Michael
P.S. knotwelkum, your observations are welcome by me.
On Tue, Sep 25, 2012 at 5:22 AM, Patrick Mylund Nielsen <
Post by Patrick Mylund Nielsen
What DisposaBoy was pointing out is that your original post basically
read, "Your error handling sucks! Some other guys said that your error
handling sucks. Why does it suck? Too bad, now I won't use your language",
and it was obvious that you haven't actually used the language yourself.
You need to use the language, or at least study (more) code written in it,
before you adopt and parrot somebody else's opinion, especially if you're
going to post such a condescending/derisive message to that language's
mailing list.
Of course, that doesn't just apply to programming languages. Many
programmers use NoSQL databases to be able to make "web scale"
applications, and not RDBMS, even though they will likely be tens or
hundreds of times as productive using something relational, and won't
actually have the problems that Facebook has for messaging (they still use
MySQL for everything else)--and one of the major reasons they're using
these solutions is that Hacker News and reddit.com/r/programming are
filled with threads that worship the latest new thing and dismisses RDBMSs
as "old and bad" (when in reality they're some of the most mature pieces of
software that exist.) Now that Google has unveiled Spanner, maybe all the
programmers who made MongoDB applications will rave about ACID,
transactional consistency and the ease-of-use of query languages... :) (It
already exists I guess: "NewSQL".)
My/our point is: Don't dismiss something because someone got to #1 on
Hacker News criticizing it. In a lot of cases, they don't really know what
they're talking about, so adopting their (misinformed) opinion is doing
yourself a disfavor. NoSQL, or exceptions, may be right for you, but that
may be the case far less often than you'd think if you ingest Hacker News
articles uncritically. Try it, then make up your own mind.
Post by k***@public.gmane.org
@DisposaBoy I do have my opinions, I just pointed to a blog that summed
it up quite nicely. If you tell me to jump of a bridge, I will probably
push you off instead. You are the one spamming the list with your reply
devoid of content. As you can see, there has been quite some interest in
my sololoquy.
Post by DisposaBoy
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking
each and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better
than what I could here.
http://uberpython.wordpress.**com/2012/09/23/why-im-not-**
leaving-python-for-go/<http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/>
http://www.yosefk.com/blog/**error-codes-vs-exceptions-**
critical-code-vs-typical-code.**html<http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html>
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
Form what you've said, it doesn't appear that you are able to form your
own opinions. What happens if I tell you that it's a good idea to go
jumping off bridges? ... In any case, please don't spam the list
--
--
--
650-335-5765
--
Peter
2012-09-25 10:52:45 UTC
Permalink
Do you mean something like:

f, panic := os.Create("filename")

where assigning a non-nil value to panic would cause it to panic?

Some kind of generalised version of this where you could do an implicit !=
nil check might make for cleaner code, but I worry about the *extra*
"mental code folding" needed to really understand something like that.
Post by Michael Jones
One positive point about exceptions: it is nice to have the "happy case"
code flow be clean. I perform a mental code folding around the expected
outcomes when reading. Sometimes my inability to do this influences my
design so that it can work out that way. In a perfect world it would be
* Error handling right at the point of return so that you can see what is
handled or not handled, how it is handled, and what types of failures are
possible.
* Error handling somewhere else so that the logic of the algorithm is
expressed purely and not obscured by a crowd of real-world constraints and
possibile woes.
Clearly a compromise is to be expected and as Dave Cheney's article
explains, the issue is about where and how to implement out-of-band
signaling. There are only so many choices and most of them have been tried
by a number of programming languages. (Though some may not be familiar with
many of those explorations.) There may be new ways, but if the choice is
between too mysterious and too explicit then I prefer Go's explicit
handling at the point of return (which is also the point of call in most
languages ;-)
If I can have new and possibly complicated language features, I might be
tempted to support something that helps with information hiding in cases
where the error handling feels redundant and bulky compared to the
underlying code.
One wonderful example of this kind of outcome is Go's defer, which factors
the proper handling of cases out of each leaf of the code path. Imagine an
error handling version along similar lines. I'll describe it here not as a
proposal, but as an unpolished but hopefully clear way to make my meaning
plain.
Imagine a magic kind of active variable where assigning non-zero to it
stored a value and also (hold your booing) caused an implicit goto. Now,
resultA, active := functionA( ... )
resultB, active := functionB( ... )
handle active {
Panic
}
This kind of thing (just a quick example at 5am in a hotel in Delhi, be
gentle with me) would allow one to "hide" the handling somewhere else when
useful, would let developers factor a number of "out of same resource and
share the same action" cases with one block of handling code, and do much
of what exceptions do magically via the stack in a visible way using the
multiple return value and a jump based on assigned data. In practice, the
active variable could just be named "handle" and the handle kind of switch
could use the implicit handle value. They could nest, maybe, or have labels
or whatnot. My point is not to suggest how to do it but to share that there
are virtues in exceptions that have nothing to do with the actual exception
mechanism, how they work in other languages, how they have been cruelly
overused, and so on.
Michael
P.S. knotwelkum, your observations are welcome by me.
On Tue, Sep 25, 2012 at 5:22 AM, Patrick Mylund Nielsen <
Post by Patrick Mylund Nielsen
What DisposaBoy was pointing out is that your original post basically
read, "Your error handling sucks! Some other guys said that your error
handling sucks. Why does it suck? Too bad, now I won't use your language",
and it was obvious that you haven't actually used the language yourself.
You need to use the language, or at least study (more) code written in it,
before you adopt and parrot somebody else's opinion, especially if you're
going to post such a condescending/derisive message to that language's
mailing list.
Of course, that doesn't just apply to programming languages. Many
programmers use NoSQL databases to be able to make "web scale"
applications, and not RDBMS, even though they will likely be tens or
hundreds of times as productive using something relational, and won't
actually have the problems that Facebook has for messaging (they still use
MySQL for everything else)--and one of the major reasons they're using
these solutions is that Hacker News and reddit.com/r/programming are
filled with threads that worship the latest new thing and dismisses RDBMSs
as "old and bad" (when in reality they're some of the most mature pieces of
software that exist.) Now that Google has unveiled Spanner, maybe all the
programmers who made MongoDB applications will rave about ACID,
transactional consistency and the ease-of-use of query languages... :) (It
already exists I guess: "NewSQL".)
My/our point is: Don't dismiss something because someone got to #1 on
Hacker News criticizing it. In a lot of cases, they don't really know what
they're talking about, so adopting their (misinformed) opinion is doing
yourself a disfavor. NoSQL, or exceptions, may be right for you, but that
may be the case far less often than you'd think if you ingest Hacker News
articles uncritically. Try it, then make up your own mind.
Post by k***@public.gmane.org
@DisposaBoy I do have my opinions, I just pointed to a blog that summed
it up quite nicely. If you tell me to jump of a bridge, I will probably
push you off instead. You are the one spamming the list with your reply
devoid of content. As you can see, there has been quite some interest in
my sololoquy.
Post by DisposaBoy
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking
each and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better
than what I could here.
http://uberpython.wordpress.**com/2012/09/23/why-im-not-**
leaving-python-for-go/<http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/>
http://www.yosefk.com/blog/**error-codes-vs-exceptions-**
critical-code-vs-typical-code.**html<http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html>
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
Form what you've said, it doesn't appear that you are able to form your
own opinions. What happens if I tell you that it's a good idea to go
jumping off bridges? ... In any case, please don't spam the list
--
--
--
| +1 650-335-5765
--
Michael Jones
2012-09-25 12:25:18 UTC
Permalink
Yes, broadly. and yes, hiding actions in an implicit behavior is both good
and bad for the reasons you say. And, as I wrote, this was just an example
(implicit branches/actions based triggered by value assigned) of the idea
that there is something nice about separating the out-of-band handling of
special case circumstances.

I'm a fan of the belief underlying Donald Knuth's WEB (weave/tangle) system
that presentation to the reader is part (perhaps most in some cases) of the
beauty and art of programming. Hiding/Showing is part of this.
Together/Separate can be part of this. In the literal example of WEB, Knuth
uses trivial macros to do much of his hiding. (Not making a case for WEB,
just pointing out that lightweight, inline macros are another way people
have tried to have it both ways.)
Post by Peter
f, panic := os.Create("filename")
where assigning a non-nil value to panic would cause it to panic?
Some kind of generalised version of this where you could do an implicit !=
nil check might make for cleaner code, but I worry about the *extra*
"mental code folding" needed to really understand something like that.
Post by Michael Jones
One positive point about exceptions: it is nice to have the "happy case"
code flow be clean. I perform a mental code folding around the expected
outcomes when reading. Sometimes my inability to do this influences my
design so that it can work out that way. In a perfect world it would be
* Error handling right at the point of return so that you can see what is
handled or not handled, how it is handled, and what types of failures are
possible.
* Error handling somewhere else so that the logic of the algorithm is
expressed purely and not obscured by a crowd of real-world constraints and
possibile woes.
Clearly a compromise is to be expected and as Dave Cheney's article
explains, the issue is about where and how to implement out-of-band
signaling. There are only so many choices and most of them have been tried
by a number of programming languages. (Though some may not be familiar with
many of those explorations.) There may be new ways, but if the choice is
between too mysterious and too explicit then I prefer Go's explicit
handling at the point of return (which is also the point of call in most
languages ;-)
If I can have new and possibly complicated language features, I might be
tempted to support something that helps with information hiding in cases
where the error handling feels redundant and bulky compared to the
underlying code.
One wonderful example of this kind of outcome is Go's defer, which
factors the proper handling of cases out of each leaf of the code path.
Imagine an error handling version along similar lines. I'll describe it
here not as a proposal, but as an unpolished but hopefully clear way to
make my meaning plain.
Imagine a magic kind of active variable where assigning non-zero to it
stored a value and also (hold your booing) caused an implicit goto. Now,
resultA, active := functionA( ... )
resultB, active := functionB( ... )
handle active {
Panic
}
This kind of thing (just a quick example at 5am in a hotel in Delhi, be
gentle with me) would allow one to "hide" the handling somewhere else when
useful, would let developers factor a number of "out of same resource and
share the same action" cases with one block of handling code, and do much
of what exceptions do magically via the stack in a visible way using the
multiple return value and a jump based on assigned data. In practice, the
active variable could just be named "handle" and the handle kind of switch
could use the implicit handle value. They could nest, maybe, or have labels
or whatnot. My point is not to suggest how to do it but to share that there
are virtues in exceptions that have nothing to do with the actual exception
mechanism, how they work in other languages, how they have been cruelly
overused, and so on.
Michael
P.S. knotwelkum, your observations are welcome by me.
On Tue, Sep 25, 2012 at 5:22 AM, Patrick Mylund Nielsen <
Post by Patrick Mylund Nielsen
What DisposaBoy was pointing out is that your original post basically
read, "Your error handling sucks! Some other guys said that your error
handling sucks. Why does it suck? Too bad, now I won't use your language",
and it was obvious that you haven't actually used the language yourself.
You need to use the language, or at least study (more) code written in it,
before you adopt and parrot somebody else's opinion, especially if you're
going to post such a condescending/derisive message to that language's
mailing list.
Of course, that doesn't just apply to programming languages. Many
programmers use NoSQL databases to be able to make "web scale"
applications, and not RDBMS, even though they will likely be tens or
hundreds of times as productive using something relational, and won't
actually have the problems that Facebook has for messaging (they still use
MySQL for everything else)--and one of the major reasons they're using
these solutions is that Hacker News and reddit.com/r/programming are
filled with threads that worship the latest new thing and dismisses RDBMSs
as "old and bad" (when in reality they're some of the most mature pieces of
software that exist.) Now that Google has unveiled Spanner, maybe all the
programmers who made MongoDB applications will rave about ACID,
transactional consistency and the ease-of-use of query languages... :) (It
already exists I guess: "NewSQL".)
My/our point is: Don't dismiss something because someone got to #1 on
Hacker News criticizing it. In a lot of cases, they don't really know what
they're talking about, so adopting their (misinformed) opinion is doing
yourself a disfavor. NoSQL, or exceptions, may be right for you, but that
may be the case far less often than you'd think if you ingest Hacker News
articles uncritically. Try it, then make up your own mind.
Post by k***@public.gmane.org
@DisposaBoy I do have my opinions, I just pointed to a blog that
summed it up quite nicely. If you tell me to jump of a bridge, I will
probably push you off instead. You are the one spamming the list with your
reply devoid of content. As you can see, there has been quite some
interest in my sololoquy.
Post by DisposaBoy
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking
each and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better
than what I could here.
http://uberpython.wordpress.**co**m/2012/09/23/why-im-not-**leavin**
g-python-for-go/<http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/>
http://www.yosefk.com/blog/**err**or-codes-vs-exceptions-**critica**
l-code-vs-typical-code.**html<http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html>
As one of the comments I read said: 99% of the time I need to code
the happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
Form what you've said, it doesn't appear that you are able to form
your own opinions. What happens if I tell you that it's a good idea to go
jumping off bridges? ... In any case, please don't spam the list
--
--
--
650-335-5765
--
--
Michael T. Jones | Chief Technology Advocate | mtj-hpIqsD4AKlfQT0dZR+***@public.gmane.org | +1
650-335-5765

--
Ian Lance Taylor
2012-09-25 12:43:30 UTC
Permalink
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=google.com; s=20120113;
h=x-beenthere:received-spf:mime-version:in-reply-to:references:date
:message-id:subject:from:to:cc:x-system-of-record:x-gm-message-state
:x-original-sender:x-original-authentication-results:precedence
:mailing-list:list-id:x-google-group-id:list-post:list-help
:list-archive:sender:list-subscribe:list-unsubscribe:content-type;
bh=QjLp12Vk0rA78uj4NviVzcYBZrLAchVlD6Y35lNwzwY=;
b=NXDmeCkWwojmlsv+tabkc/IMHxXm1VJUofjhFzMFsk0uzq3a5ouEhicg2mdgdWxqv5
dv4xAMi57FGlJ3cohCYrLiC+hfPs+t6xbdeL4qXe31eV3CTqjsFZWJ+U88s5jeDzoMf/
ccRRcnC8ar/lvW9KRJeuh/btImsh7JRip/6e0DPpsh+BOET2lJ4DhjPmxGK4uAFU/Es9
dYuWLga9D6APDaSmtkDX6eO4wElFg2cj5V/40+pAzrVEwidaz+tYybs1I+RFaHtPkQ3y
dcnFYKXz/HLwNXotjtR+hWvLbqUYBl4/jUKmDS+djui25BfySurpjg
Received: by 10.68.189.202 with SMTP id gk10mr3609925pbc.11.1348577014176;
Tue, 25 Sep 2012 05:43:34 -0700 (PDT)
X-BeenThere: golang-nuts-/***@public.gmane.org
Received: by 10.68.222.169 with SMTP id qn9ls450070pbc.4.gmail; Tue, 25 Sep
2012 05:43:31 -0700 (PDT)
Received: by 10.66.82.98 with SMTP id h2mr2895964pay.27.1348577011425;
Tue, 25 Sep 2012 05:43:31 -0700 (PDT)
Received: by 10.66.82.98 with SMTP id h2mr2895963pay.27.1348577011314;
Tue, 25 Sep 2012 05:43:31 -0700 (PDT)
Received: from mail-pb0-f44.google.com (mail-pb0-f44.google.com [209.85.160.44])
by gmr-mx.google.com with ESMTPS id o10si46123pax.0.2012.09.25.05.43.31
(version=TLSv1/SSLv3 cipher=OTHER);
Tue, 25 Sep 2012 05:43:31 -0700 (PDT)
Received-SPF: pass (google.com: domain of iant-hpIqsD4AKlfQT0dZR+***@public.gmane.org designates 209.85.160.44 as permitted sender) client-ip=209.85.160.44;
Received: by pbbro8 with SMTP id ro8so72467pbb.17
for <golang-nuts-/***@public.gmane.org>; Tue, 25 Sep 2012 05:43:31 -0700 (PDT)
Received: by 10.66.87.66 with SMTP id v2mr40447499paz.71.1348577011172;
Tue, 25 Sep 2012 05:43:31 -0700 (PDT)
Received: by 10.66.87.66 with SMTP id v2mr40447456paz.71.1348577010840; Tue,
25 Sep 2012 05:43:30 -0700 (PDT)
Received: by 10.68.129.170 with HTTP; Tue, 25 Sep 2012 05:43:30 -0700 (PDT)
In-Reply-To: <082eddd8-5f46-4c2b-9559-c5be04cec234-/***@public.gmane.org>
X-System-Of-Record: true
X-Gm-Message-State: ALoCoQlcjUIf9v8NWhuiXGw3VixyItutwI11zz+KW6cYUoZ+bbKcGO4KYcxZUGgE87f8jT8hYuD0i/mtvA74NxcZ66dca/poFqoEx1rjs9UR+YvJxgREJ4APcacOP+BSLdxipHbnrWMNIqnles4QX5Akzw1xW5VmMaAPqIcCe8CSZGDKgU39HDTmGsRVGeNsezvcC1MBSLU3OZg74hXPRGxh+Nf9uZ8DdQ==
X-Original-Sender: iant-hpIqsD4AKlfQT0dZR+***@public.gmane.org
X-Original-Authentication-Results: gmr-mx.google.com; spf=pass (google.com:
domain of iant-hpIqsD4AKlfQT0dZR+***@public.gmane.org designates 209.85.160.44 as permitted sender)
smtp.mail=iant-hpIqsD4AKlfQT0dZR+***@public.gmane.org; dkim=pass header.i=@google.com
Precedence: list
Mailing-list: list golang-nuts-/***@public.gmane.org; contact golang-nuts+owners-/***@public.gmane.org
List-ID: <golang-nuts.googlegroups.com>
X-Google-Group-Id: 332403668183
List-Post: <http://groups.google.com/group/golang-nuts/post?hl=en-US>, <mailto:golang-nuts-/***@public.gmane.org>
List-Help: <http://groups.google.com/support/?hl=en-US>, <mailto:golang-nuts+help-/***@public.gmane.org>
List-Archive: <http://groups.google.com/group/golang-nuts?hl=en-US>
Sender: golang-nuts-/***@public.gmane.org
List-Subscribe: <http://groups.google.com/group/golang-nuts/subscribe?hl=en-US>,
<mailto:golang-nuts+subscribe-/***@public.gmane.org>
List-Unsubscribe: <http://groups.google.com/group/golang-nuts/subscribe?hl=en-US>,
<mailto:googlegroups-manage+332403668183+unsubscribe-/***@public.gmane.org>
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.go.general/72349>
Post by Peter
f, panic := os.Create("filename")
where assigning a non-nil value to panic would cause it to panic?
That's kind of interesting. I don't see quite how to make it work
with panic, but I see how it could work with return, which is a
keyword. One could say that
f, return = os.Create("filename")
was permitted if 1) the function being called returns a parameter of
the builtin type error at the point the return keyword is used; 2) the
function making the call returns a single parameter of the builtin
type error. It would mean: if the value assigned to the "return"
keyword is non-nil, then the calling function immediately returns,
with that value as the error result, and with the other results
holding whatever value they hold at that point (if the results are
unnamed, zero).

Magic syntactic sugar, yes, but not too hard to understand. Might be
overused, though, and doesn't help with the problem of ignoring the
result entirely, e.g., of f.Close().

Ian

--
Jan Mercl
2012-09-25 13:12:56 UTC
Permalink
Post by Ian Lance Taylor
That's kind of interesting. I don't see quite how to make it work
with panic, but I see how it could work with return, which is a
keyword. One could say that
f, return = os.Create("filename")
was permitted if 1) the function being called returns a parameter of
the builtin type error at the point the return keyword is used; 2) the
function making the call returns a single parameter of the builtin
type error. It would mean: if the value assigned to the "return"
keyword is non-nil, then the calling function immediately returns,
with that value as the error result, and with the other results
holding whatever value they hold at that point (if the results are
unnamed, zero).
That would make for a (sometimes) big SLOC reduction, so I kinda like
it. But the newly introduced invisibility of 'if err != nil' is IMO a
cost too big to afford comfortably.

-j

--
Michael Jones
2012-09-25 13:50:40 UTC
Permalink
I had imagined also being able to get to a switch statement via this
mechanism. That lets common handling be centralized. (shown in first email)
But the key mechanism is that non-nil / non-zero assignment means "take an
action"
Post by Ian Lance Taylor
Post by Peter
f, panic := os.Create("filename")
where assigning a non-nil value to panic would cause it to panic?
That's kind of interesting. I don't see quite how to make it work
with panic, but I see how it could work with return, which is a
keyword. One could say that
f, return = os.Create("filename")
was permitted if 1) the function being called returns a parameter of
the builtin type error at the point the return keyword is used; 2) the
function making the call returns a single parameter of the builtin
type error. It would mean: if the value assigned to the "return"
keyword is non-nil, then the calling function immediately returns,
with that value as the error result, and with the other results
holding whatever value they hold at that point (if the results are
unnamed, zero).
Magic syntactic sugar, yes, but not too hard to understand. Might be
overused, though, and doesn't help with the problem of ignoring the
result entirely, e.g., of f.Close().
Ian
--
--
Michael T. Jones | Chief Technology Advocate | mtj-hpIqsD4AKlfQT0dZR+***@public.gmane.org | +1
650-335-5765

--
yy
2012-09-25 14:09:09 UTC
Permalink
Post by Michael Jones
I had imagined also being able to get to a switch statement via this
mechanism. That lets common handling be centralized. (shown in first email)
But the key mechanism is that non-nil / non-zero assignment means "take an
action"
You could use defer:

defer func() {
switch err { // assume err is the name of the return value
case memoryError:
:
case diskExploded:
:
case alienInvasion:
Panic
}
}()

:
resultA, return := functionA( ... )
:
resultB, return := functionB( ... )
:

I preferred your original solution (if we are adding sugar, let's make
it as sweet as possible), but I'm not completely sure about all this.
However, it looks like an interesting idea and, well matured, it may
be a good candidate for a future (long term future) version of the
language.
--
- yiyus || JGL .

--
Peter
2012-09-25 15:41:48 UTC
Permalink
This is an interesting idea Michael, thanks.

IMO,
if I am writing production code I don't mind the errors being handled
explicitly and simply, even if a little verbosely.
However when writing prototype code I would like a way to handle errors
without confusing debugging, i.e. I'd like to code
for the working case and patch up errors as I find them, but without
spending effort tracking them down.
Some sugar that makes all errors fatal (by panicking with a trace) would
provide some support, but I'm not sure that would handle ignored errors,
especially ones from fmt.Println, etc, which I want to implicitly ignore.

The amount of error handling in Go makes me appreciate how much other
languages ignore them. In the same way that I worry about
making a typo in a variable name if coding in Javascript, I am also
suddenly aware of a variety of failure modes.
Post by Michael Jones
I had imagined also being able to get to a switch statement via this
mechanism. That lets common handling be centralized. (shown in first email)
But the key mechanism is that non-nil / non-zero assignment means "take an
action"
Post by Ian Lance Taylor
Post by Peter
f, panic := os.Create("filename")
where assigning a non-nil value to panic would cause it to panic?
That's kind of interesting. I don't see quite how to make it work
with panic, but I see how it could work with return, which is a
keyword. One could say that
f, return = os.Create("filename")
was permitted if 1) the function being called returns a parameter of
the builtin type error at the point the return keyword is used; 2) the
function making the call returns a single parameter of the builtin
type error. It would mean: if the value assigned to the "return"
keyword is non-nil, then the calling function immediately returns,
with that value as the error result, and with the other results
holding whatever value they hold at that point (if the results are
unnamed, zero).
Magic syntactic sugar, yes, but not too hard to understand. Might be
overused, though, and doesn't help with the problem of ignoring the
result entirely, e.g., of f.Close().
Ian
--
--
| +1 650-335-5765
--
Ian Lance Taylor
2012-09-25 15:43:15 UTC
Permalink
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=google.com; s=20120113;
h=x-beenthere:received-spf:mime-version:in-reply-to:references:date
:message-id:subject:from:to:cc:x-system-of-record:x-gm-message-state
:x-original-sender:x-original-authentication-results:precedence
:mailing-list:list-id:x-google-group-id:list-post:list-help
:list-archive:sender:list-subscribe:list-unsubscribe:content-type;
bh=xjlsuUjBttA9ueBsy8nLpKjAIFZhZbdErB2kJ2F93/c=;
b=RseTAMwG8RdSd0keKWzRKYrhTVQg9ZKALC5Vf6rBpgLRWz8AEeHJIQexGsAOo4RaiZ
dYH+jQFvNJZoNfBVRqCQJxey27ZjKAnG/w4/3tximszV5qpJ/MqozLI7a4In+Wn0JzD3
B2B5vMCoBFUUfihw+jk8zdipeNgJrGdvfvD/TvodVtbbeHi1MGL18B1/ZTTK6hos2iL8
8AV6vaN3Q5HEgil/gmLtwqVXR+E/GaNm3f/5qAJCFtpRJj7wujnq1VAkJWTCAvxy1+Fb
Wdxwo4MxcqgpG22kuO1+o8cTxnio5lyzituKflMrGDKycXNhArdyCY
Received: by 10.68.234.193 with SMTP id ug1mr3429241pbc.19.1348587798695;
Tue, 25 Sep 2012 08:43:18 -0700 (PDT)
X-BeenThere: golang-nuts-/***@public.gmane.org
Received: by 10.68.237.161 with SMTP id vd1ls1194297pbc.3.gmail; Tue, 25 Sep
2012 08:43:16 -0700 (PDT)
Received: by 10.66.90.36 with SMTP id bt4mr3405119pab.5.1348587795998;
Tue, 25 Sep 2012 08:43:15 -0700 (PDT)
Received: by 10.66.90.36 with SMTP id bt4mr3405118pab.5.1348587795957;
Tue, 25 Sep 2012 08:43:15 -0700 (PDT)
Received: from mail-pb0-f53.google.com (mail-pb0-f53.google.com [209.85.160.53])
by gmr-mx.google.com with ESMTPS id p7si217934pby.0.2012.09.25.08.43.15
(version=TLSv1/SSLv3 cipher=OTHER);
Tue, 25 Sep 2012 08:43:15 -0700 (PDT)
Received-SPF: pass (google.com: domain of iant-hpIqsD4AKlfQT0dZR+***@public.gmane.org designates 209.85.160.53 as permitted sender) client-ip=209.85.160.53;
Received: by pbcwz12 with SMTP id wz12so328408pbc.40
for <golang-nuts-/***@public.gmane.org>; Tue, 25 Sep 2012 08:43:15 -0700 (PDT)
Received: by 10.66.88.233 with SMTP id bj9mr41664753pab.72.1348587795837;
Tue, 25 Sep 2012 08:43:15 -0700 (PDT)
Received: by 10.66.88.233 with SMTP id bj9mr41664725pab.72.1348587795658; Tue,
25 Sep 2012 08:43:15 -0700 (PDT)
Received: by 10.68.129.170 with HTTP; Tue, 25 Sep 2012 08:43:15 -0700 (PDT)
In-Reply-To: <CAB3Vzbo=waR636XBSQyAVcSuizYOhC+JrHvdf-_SRJkpk9Kqmg-JsoAwUIsXosN+***@public.gmane.org>
X-System-Of-Record: true
X-Gm-Message-State: ALoCoQkhQGd/thdPmG08+OZFqq9sWuZ00rERdNgal5OmjqspsBAK9aPJLPVT6rxj0SujvAhrCK9tx3VIywK2YPlzSRrNWpYFtjbmQ/kDUPgMuEVHrJmPWbkxWV7aIMMNWaBBu0BU+zIwAomoq9itBWc3jNCIW53dJYZQ9Rtf2IDq8k8NnwrYFi1OGf+qXJ19yL8y96YD1PoP3EL1/Fpygf8p6RjedrEt7w==
X-Original-Sender: iant-hpIqsD4AKlfQT0dZR+***@public.gmane.org
X-Original-Authentication-Results: gmr-mx.google.com; spf=pass (google.com:
domain of iant-hpIqsD4AKlfQT0dZR+***@public.gmane.org designates 209.85.160.53 as permitted sender)
smtp.mail=iant-hpIqsD4AKlfQT0dZR+***@public.gmane.org; dkim=pass header.i=@google.com
Precedence: list
Mailing-list: list golang-nuts-/***@public.gmane.org; contact golang-nuts+owners-/***@public.gmane.org
List-ID: <golang-nuts.googlegroups.com>
X-Google-Group-Id: 332403668183
List-Post: <http://groups.google.com/group/golang-nuts/post?hl=en-US>, <mailto:golang-nuts-/***@public.gmane.org>
List-Help: <http://groups.google.com/support/?hl=en-US>, <mailto:golang-nuts+help-/***@public.gmane.org>
List-Archive: <http://groups.google.com/group/golang-nuts?hl=en-US>
Sender: golang-nuts-/***@public.gmane.org
List-Subscribe: <http://groups.google.com/group/golang-nuts/subscribe?hl=en-US>,
<mailto:golang-nuts+subscribe-/***@public.gmane.org>
List-Unsubscribe: <http://groups.google.com/group/golang-nuts/subscribe?hl=en-US>,
<mailto:googlegroups-manage+332403668183+unsubscribe-/***@public.gmane.org>
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.go.general/72383>
Post by Michael Jones
I had imagined also being able to get to a switch statement via this
mechanism. That lets common handling be centralized. (shown in first email)
But the key mechanism is that non-nil / non-zero assignment means "take an
action"
Yeah, my idea is laughably non-general. But here is a different idea,
that is more like yours: let labels be variables. A read from a label
is just an ordinary read. When writing to a label, though, if the
value is non-zero, the program does a goto the label.

Then we can write

func F(filename string) error {
f, err := os.Open(filename)
_, err = f.Write("hi")
err = f.Close()
fmt.Println("done")
return nil
err:
return err
}

And since I can't let well enough alone, let's permit this same idea
with the special label "return", where of course it is only meaningful
to use the label name as a result parameter.

func F(filename string) (return error) {
f, return := os.Open(filename)
_, return = f.Write("hi")
return = f.Close()
fmt.Println("done")
return nil
}

No special handling of the error type, very little additional syntax
(permit the return keyword in a couple more places, and permit an
optional type on the label declaration so we can write "foo
interface{}:").

Ian
Post by Michael Jones
Post by Ian Lance Taylor
Post by Peter
f, panic := os.Create("filename")
where assigning a non-nil value to panic would cause it to panic?
That's kind of interesting. I don't see quite how to make it work
with panic, but I see how it could work with return, which is a
keyword. One could say that
f, return = os.Create("filename")
was permitted if 1) the function being called returns a parameter of
the builtin type error at the point the return keyword is used; 2) the
function making the call returns a single parameter of the builtin
type error. It would mean: if the value assigned to the "return"
keyword is non-nil, then the calling function immediately returns,
with that value as the error result, and with the other results
holding whatever value they hold at that point (if the results are
unnamed, zero).
Magic syntactic sugar, yes, but not too hard to understand. Might be
overused, though, and doesn't help with the problem of ignoring the
result entirely, e.g., of f.Close().
Ian
--
--
650-335-5765
--
Daniel Morsing
2012-09-25 16:20:50 UTC
Permalink
Post by Ian Lance Taylor
func F(filename string) error {
f, err := os.Open(filename)
_, err = f.Write("hi")
err = f.Close()
fmt.Println("done")
return nil
return err
}
I really don't like this. Seemingly unrelated actions that have
non-local effects would be a bad idea to introduce to go. It has
problems when you have a 3 screen long function where you cannot see
the label when you first start reading it.

It also breaks go1 compatibility since labels can be the same name as
variables right now.

The other ideas are promising. A bit too magical for my tastes but I
think they could be made less magical through the use of a good syntax
(Which I'm not going to start bikeshedding right now).

--
Michael Jones
2012-09-25 17:33:00 UTC
Permalink
I like it. Looks clean and clear (at least, once one accepts the magic
implicit jump.)

Now, let's get in the Wayback machine and have a look at what came before.
Donald Knuth wrote "Structured Programming with Go To Statements" in 1974.

Knuth, "Structured Programming with Go To Statements"
http://sbel.wisc.edu/Courses/ME964/Literature/knuthProgramming1974.pdf

That paper is a survey on being general, efficient, and retaining clarity.
One of the
gems in that paper is something I mentioned here recently, Charles Zahn's
event
indicators. In the paper Knuth suggests a parameterized extension of them.
Our
thinking here is a minimalist reduction of their key point, implemented in
a more
general framework. The ideas are close enough that Zahn's construction with
Knuth's extension offers us some guidance. Indeed, all that Knuth writes in
the
paper deserves the closest study in connection with this discussion, as
does
Zahn's paper and his notion of "conceptual distance."

Zahn, "Structured Control in Programming Languages"
http://www.slac.stanford.edu/cgi-wrap/getdoc/slac-pub-1530.pdf

I like our scheme better, but acknowledge and respect all that comes
before. If you
read the above and think about the meaning more than the literal, then
you'll see that
assignment in our magic action variables/labels has the power of
Knuth's parameter
extension to Zahn's idea, the name of the label/variable pays the role of
the
event indicator, and the magic jump on non-zero assignment is the new
wrinkle
that adds either confusion or clarity depending on your point of view. ;-)
Post by Michael Jones
Post by Michael Jones
I had imagined also being able to get to a switch statement via this
mechanism. That lets common handling be centralized. (shown in first
email)
Post by Michael Jones
But the key mechanism is that non-nil / non-zero assignment means "take
an
Post by Michael Jones
action"
Yeah, my idea is laughably non-general. But here is a different idea,
that is more like yours: let labels be variables. A read from a label
is just an ordinary read. When writing to a label, though, if the
value is non-zero, the program does a goto the label.
Then we can write
func F(filename string) error {
f, err := os.Open(filename)
_, err = f.Write("hi")
err = f.Close()
fmt.Println("done")
return nil
return err
}
And since I can't let well enough alone, let's permit this same idea
with the special label "return", where of course it is only meaningful
to use the label name as a result parameter.
func F(filename string) (return error) {
f, return := os.Open(filename)
_, return = f.Write("hi")
return = f.Close()
fmt.Println("done")
return nil
}
No special handling of the error type, very little additional syntax
(permit the return keyword in a couple more places, and permit an
optional type on the label declaration so we can write "foo
interface{}:").
Ian
Post by Michael Jones
Post by Ian Lance Taylor
Post by Peter
f, panic := os.Create("filename")
where assigning a non-nil value to panic would cause it to panic?
That's kind of interesting. I don't see quite how to make it work
with panic, but I see how it could work with return, which is a
keyword. One could say that
f, return = os.Create("filename")
was permitted if 1) the function being called returns a parameter of
the builtin type error at the point the return keyword is used; 2) the
function making the call returns a single parameter of the builtin
type error. It would mean: if the value assigned to the "return"
keyword is non-nil, then the calling function immediately returns,
with that value as the error result, and with the other results
holding whatever value they hold at that point (if the results are
unnamed, zero).
Magic syntactic sugar, yes, but not too hard to understand. Might be
overused, though, and doesn't help with the problem of ignoring the
result entirely, e.g., of f.Close().
Ian
--
--
650-335-5765
--
Michael T. Jones | Chief Technology Advocate | mtj-hpIqsD4AKlfQT0dZR+***@public.gmane.org | +1
650-335-5765

--
Alexander Neumann
2012-09-25 18:46:43 UTC
Permalink
I like the "return" variant, not sure about the more general idea with
labels. Would be nice to see something like this materialize in a not too
distant version of Go.

Also reminds me of this old thread:
https://groups.google.com/forum/?fromgroups#!msg/golang-nuts/Usm5eRDzatU/XWPpWOlMiOYJ

-- Alex
Post by Michael Jones
Post by Michael Jones
I had imagined also being able to get to a switch statement via this
mechanism. That lets common handling be centralized. (shown in first
email)
Post by Michael Jones
But the key mechanism is that non-nil / non-zero assignment means "take
an
Post by Michael Jones
action"
Yeah, my idea is laughably non-general. But here is a different idea,
that is more like yours: let labels be variables. A read from a label
is just an ordinary read. When writing to a label, though, if the
value is non-zero, the program does a goto the label.
Then we can write
func F(filename string) error {
f, err := os.Open(filename)
_, err = f.Write("hi")
err = f.Close()
fmt.Println("done")
return nil
return err
}
And since I can't let well enough alone, let's permit this same idea
with the special label "return", where of course it is only meaningful
to use the label name as a result parameter.
func F(filename string) (return error) {
f, return := os.Open(filename)
_, return = f.Write("hi")
return = f.Close()
fmt.Println("done")
return nil
}
No special handling of the error type, very little additional syntax
(permit the return keyword in a couple more places, and permit an
optional type on the label declaration so we can write "foo
interface{}:").
Ian
Post by Michael Jones
Post by Ian Lance Taylor
Post by Peter
f, panic := os.Create("filename")
where assigning a non-nil value to panic would cause it to panic?
That's kind of interesting. I don't see quite how to make it work
with panic, but I see how it could work with return, which is a
keyword. One could say that
f, return = os.Create("filename")
was permitted if 1) the function being called returns a parameter of
the builtin type error at the point the return keyword is used; 2) the
function making the call returns a single parameter of the builtin
type error. It would mean: if the value assigned to the "return"
keyword is non-nil, then the calling function immediately returns,
with that value as the error result, and with the other results
holding whatever value they hold at that point (if the results are
unnamed, zero).
Magic syntactic sugar, yes, but not too hard to understand. Might be
overused, though, and doesn't help with the problem of ignoring the
result entirely, e.g., of f.Close().
Ian
--
--
650-335-5765
--
Lucio
2012-09-25 16:04:49 UTC
Permalink
We want two things here: the alert (exception) and the return value, with
options to declare either
or both, well, optional. This smacks of "channel" to me, where the
appearance of a value triggers
further processing. The Tcl notion of a catch wrapper also contributes to
the concept, so that we
would have a "catch" invocation which would pass the "error" result value
to a channel receiver,
the latter being the exception handler. Does it make any sense?

Given the existing Go structure, we could do it with a special "catch"
wrapper for each function type,
but a general "catch" wrapper would provide the useful syntactic sugar.
Not unlike the "go" prefix,
actually, in principle, except that we somehow have to specify the target
function.

Let me see

catch n, err := b.Read(buf); except <- err

...sort of thing?

I don't quite like it, but this is what I want to put on the table for
further discussion.

Lucio.

--
Nigel Tao
2012-09-25 23:16:20 UTC
Permalink
Post by Ian Lance Taylor
One could say that
f, return = os.Create("filename")
was permitted
It's mostly academic at this point, but if we're brainstorming new
syntax, another (half-baked) idea is something like:

$ is an operator that can only be used inside a function (let's call
it f) that returns (ret0, ret1, ..., retN, error). Suppose g is a
function or method called inside f, and g(etc) would normally return
(a, b, err). $g(etc) would mean (a, b) if err is nil, otherwise f
returns (zero0, zero1, ..., zeroN, err).


For example:

n, err := fmt.Fprintf(w, "hello\n")
if err != nil {
return err
}

could become

n := $fmt.Fprintf(w, "hello\n")

and

func readAllZlib(r io.Reader) ([]byte, error) {
zr, err := zlib.NewReader(r)
if err != nil {
return nil, err
}
return ioutil.ReadAll(zr)
}

could become

func readAllZlib(r io.Reader) ([]byte, error) {
return ioutil.ReadAll($zlib.NewReader(r))
}


I'm not sure if I actually like the idea. It does save some
boilerplate, but it also discourages adding extra context to errors:

if err != nil {
return nil, fmt.Errorf("http: error connecting to proxy %s: %v",
cm.proxyURL, err)
}

is more useful than

if err != nil {
return nil, err
}

--
Josh Holland
2012-09-26 08:02:36 UTC
Permalink
The problem I have with all of this syntax changing magic is that it makes
it harder to see that the error actually is being handled. With the full
"if err != nil { }" form, it is clear that the possibility of error is
considered. However with the proposed "n, return = writer.Write(buf)" and $
styles, it's easy to miss the handling. A drastic change in control flow
like returning should always stand out in its own statement.

Thanks,
Josh
Post by Nigel Tao
Post by Ian Lance Taylor
One could say that
f, return = os.Create("filename")
was permitted
It's mostly academic at this point, but if we're brainstorming new
$ is an operator that can only be used inside a function (let's call
it f) that returns (ret0, ret1, ..., retN, error). Suppose g is a
function or method called inside f, and g(etc) would normally return
(a, b, err). $g(etc) would mean (a, b) if err is nil, otherwise f
returns (zero0, zero1, ..., zeroN, err).
n, err := fmt.Fprintf(w, "hello\n")
if err != nil {
return err
}
could become
n := $fmt.Fprintf(w, "hello\n")
and
func readAllZlib(r io.Reader) ([]byte, error) {
zr, err := zlib.NewReader(r)
if err != nil {
return nil, err
}
return ioutil.ReadAll(zr)
}
could become
func readAllZlib(r io.Reader) ([]byte, error) {
return ioutil.ReadAll($zlib.NewReader(r))
}
I'm not sure if I actually like the idea. It does save some
if err != nil {
return nil, fmt.Errorf("http: error connecting to proxy %s: %v",
cm.proxyURL, err)
}
is more useful than
if err != nil {
return nil, err
}
--
--
Michael Jones
2012-09-26 08:30:04 UTC
Permalink
Absolutely -- it needs to be clear. What we've been musing about is what it
might achieve and how few "magic" things would be needed to do that. If a
consensus built around it being an answer to a problem worth solving then
indeed the serious design would need to be very clear to the coder, the
debugger, and a stranger who looks at the code in 5 years.

Here is an example (just an example of the top of my head) how the example
you cite could be clear as day:

root, handle(rangeError) := sqrt(-5.0)
x = (4+j)/(root + 1)
return x

handle {
case rangeError:
:
return error("complex root")
case overflow:
:
}


this would add a new reserved word, let it appear as a "handle function
call" with the rule that the call only happens when the assigned value is
non-nil or non-xero. The call would be to the innermost handle switch. if
you wanted the "call" could act as such a jump back top to the call site if
the case does not return. Ot it could always return, or whatever.

This may not be the best way to reduce the idea to practice, but it gives
an example of ways to make the "I just might branch somewhere" logic
explicit. No doubt sophisticated language designers could think of
something much better. I just wanted to raise the idea that one nice
feature of exceptions is the ability to disaggregate the call site and the
error handling code should that be desired in a particular situation. One
that I like would be handling the same problem with the same resolution in
20 places (something like "connection dropped" or "SIgnaling NaN" where
that could serve a possibly large function with dozens of call sites. The
existing ", ok" idiom would continue to work great in all the places where
you wanted to handle the error there at the call site.

If the mechanism were general and policy free (nothing about errors, just
good for handling them like defer and closing things) then you could also
use it as an interesting implementation method for decision tables, complex
branch structures of the kind in the Knuth paper I linked above, and other
"non-local but logical" places where goto would otherwise be used.
Post by Josh Holland
The problem I have with all of this syntax changing magic is that it makes
it harder to see that the error actually is being handled. With the full
"if err != nil { }" form, it is clear that the possibility of error is
considered. However with the proposed "n, return = writer.Write(buf)" and $
styles, it's easy to miss the handling. A drastic change in control flow
like returning should always stand out in its own statement.
Thanks,
Josh
Post by Nigel Tao
Post by Ian Lance Taylor
One could say that
f, return = os.Create("filename")
was permitted
It's mostly academic at this point, but if we're brainstorming new
$ is an operator that can only be used inside a function (let's call
it f) that returns (ret0, ret1, ..., retN, error). Suppose g is a
function or method called inside f, and g(etc) would normally return
(a, b, err). $g(etc) would mean (a, b) if err is nil, otherwise f
returns (zero0, zero1, ..., zeroN, err).
n, err := fmt.Fprintf(w, "hello\n")
if err != nil {
return err
}
could become
n := $fmt.Fprintf(w, "hello\n")
and
func readAllZlib(r io.Reader) ([]byte, error) {
zr, err := zlib.NewReader(r)
if err != nil {
return nil, err
}
return ioutil.ReadAll(zr)
}
could become
func readAllZlib(r io.Reader) ([]byte, error) {
return ioutil.ReadAll($zlib.NewReader(r))
}
I'm not sure if I actually like the idea. It does save some
if err != nil {
return nil, fmt.Errorf("http: error connecting to proxy %s: %v",
cm.proxyURL, err)
}
is more useful than
if err != nil {
return nil, err
}
--
--
--
Michael T. Jones | Chief Technology Advocate | mtj-hpIqsD4AKlfQT0dZR+***@public.gmane.org | +1
650-335-5765

--
Ethan Burns
2012-09-26 12:15:42 UTC
Permalink
This idea is interesting, but I it seems to be adding a rather large new
concept to the language. I wonder how this is better than Ian's original
idea of assigning to 'return' coupled with defer (as pointed out by yiyus).
It seems like the return-based approach would be adding something simple
and orthogonal (I cringe at this cliche now, but it is the case
none-the-less). In other words, you get the out-of-band error handling
that you want by combining this hypothetical return-assignment approach
with something that already exists in the language, namely defer. Another
other benefit of the return-based approach is that, in many cases, the
error is just being passed back up the call stack and more complex handling
is not desired. Finally, because defer works on any function call, it is
possible that common error handling could be captured in a separate
function that is re-used in many defer calls.


Best,
Ethan
Post by Michael Jones
Absolutely -- it needs to be clear. What we've been musing about is what
it might achieve and how few "magic" things would be needed to do that. If
a consensus built around it being an answer to a problem worth solving then
indeed the serious design would need to be very clear to the coder, the
debugger, and a stranger who looks at the code in 5 years.
Here is an example (just an example of the top of my head) how the example
root, handle(rangeError) := sqrt(-5.0)
x = (4+j)/(root + 1)
return x
handle {
return error("complex root")
}
this would add a new reserved word, let it appear as a "handle function
call" with the rule that the call only happens when the assigned value is
non-nil or non-xero. The call would be to the innermost handle switch. if
you wanted the "call" could act as such a jump back top to the call site if
the case does not return. Ot it could always return, or whatever.
This may not be the best way to reduce the idea to practice, but it gives
an example of ways to make the "I just might branch somewhere" logic
explicit. No doubt sophisticated language designers could think of
something much better. I just wanted to raise the idea that one nice
feature of exceptions is the ability to disaggregate the call site and the
error handling code should that be desired in a particular situation. One
that I like would be handling the same problem with the same resolution in
20 places (something like "connection dropped" or "SIgnaling NaN" where
that could serve a possibly large function with dozens of call sites. The
existing ", ok" idiom would continue to work great in all the places where
you wanted to handle the error there at the call site.
If the mechanism were general and policy free (nothing about errors, just
good for handling them like defer and closing things) then you could also
use it as an interesting implementation method for decision tables, complex
branch structures of the kind in the Knuth paper I linked above, and other
"non-local but logical" places where goto would otherwise be used.
Post by Josh Holland
The problem I have with all of this syntax changing magic is that it
makes it harder to see that the error actually is being handled. With the
full "if err != nil { }" form, it is clear that the possibility of error is
considered. However with the proposed "n, return = writer.Write(buf)" and $
styles, it's easy to miss the handling. A drastic change in control flow
like returning should always stand out in its own statement.
Thanks,
Josh
Post by Nigel Tao
Post by Ian Lance Taylor
One could say that
f, return = os.Create("filename")
was permitted
It's mostly academic at this point, but if we're brainstorming new
$ is an operator that can only be used inside a function (let's call
it f) that returns (ret0, ret1, ..., retN, error). Suppose g is a
function or method called inside f, and g(etc) would normally return
(a, b, err). $g(etc) would mean (a, b) if err is nil, otherwise f
returns (zero0, zero1, ..., zeroN, err).
n, err := fmt.Fprintf(w, "hello\n")
if err != nil {
return err
}
could become
n := $fmt.Fprintf(w, "hello\n")
and
func readAllZlib(r io.Reader) ([]byte, error) {
zr, err := zlib.NewReader(r)
if err != nil {
return nil, err
}
return ioutil.ReadAll(zr)
}
could become
func readAllZlib(r io.Reader) ([]byte, error) {
return ioutil.ReadAll($zlib.NewReader(r))
}
I'm not sure if I actually like the idea. It does save some
if err != nil {
return nil, fmt.Errorf("http: error connecting to proxy %s: %v",
cm.proxyURL, err)
}
is more useful than
if err != nil {
return nil, err
}
--
--
--
| +1 650-335-5765
--
Michael Jones
2012-09-26 13:34:09 UTC
Permalink
I agree. I like that specific feature too. Just illustrating realms of
solutions for people with early questions about specifics. To me it seems
that the most interesting questions now are,

Q1: When and why would you want to separate the the code making the call
from the code handling exceptional situations? This feels good to me for
some cases, as when 20 call sites want to handle the same error, or when
the code is very complex and I would be concerned that robust error
checking in situ would obscure it. I don't know if others even feel the
need in their type of programming.

Q2: When and why would you want to have many instances of the minimal
",ok", "ok != nil", "return error to caller" in your code. If this is a
sufficiently high frequency case, then maybe it is worth facilitating with
some error-handling-and-sending-up-the-call-chain version of a function
call or result assignment. (For example, instead of "go func" you could
have "try func" with the return the last arg if not nil logic.)
From answers to these and related questions will flow knowledge of the best
path...
This idea is interesting, but I it seems to be adding a rather large new
concept to the language. I wonder how this is better than Ian's original
idea of assigning to 'return' coupled with defer (as pointed out by yiyus).
It seems like the return-based approach would be adding something simple
and orthogonal (I cringe at this cliche now, but it is the case
none-the-less). In other words, you get the out-of-band error handling
that you want by combining this hypothetical return-assignment approach
with something that already exists in the language, namely defer. Another
other benefit of the return-based approach is that, in many cases, the
error is just being passed back up the call stack and more complex handling
is not desired. Finally, because defer works on any function call, it is
possible that common error handling could be captured in a separate
function that is re-used in many defer calls.
Best,
Ethan
Post by Michael Jones
Absolutely -- it needs to be clear. What we've been musing about is what
it might achieve and how few "magic" things would be needed to do that. If
a consensus built around it being an answer to a problem worth solving then
indeed the serious design would need to be very clear to the coder, the
debugger, and a stranger who looks at the code in 5 years.
Here is an example (just an example of the top of my head) how the
root, handle(rangeError) := sqrt(-5.0)
x = (4+j)/(root + 1)
return x
handle {
return error("complex root")
}
this would add a new reserved word, let it appear as a "handle function
call" with the rule that the call only happens when the assigned value is
non-nil or non-xero. The call would be to the innermost handle switch. if
you wanted the "call" could act as such a jump back top to the call site if
the case does not return. Ot it could always return, or whatever.
This may not be the best way to reduce the idea to practice, but it gives
an example of ways to make the "I just might branch somewhere" logic
explicit. No doubt sophisticated language designers could think of
something much better. I just wanted to raise the idea that one nice
feature of exceptions is the ability to disaggregate the call site and the
error handling code should that be desired in a particular situation. One
that I like would be handling the same problem with the same resolution in
20 places (something like "connection dropped" or "SIgnaling NaN" where
that could serve a possibly large function with dozens of call sites. The
existing ", ok" idiom would continue to work great in all the places where
you wanted to handle the error there at the call site.
If the mechanism were general and policy free (nothing about errors, just
good for handling them like defer and closing things) then you could also
use it as an interesting implementation method for decision tables, complex
branch structures of the kind in the Knuth paper I linked above, and other
"non-local but logical" places where goto would otherwise be used.
Post by Josh Holland
The problem I have with all of this syntax changing magic is that it
makes it harder to see that the error actually is being handled. With the
full "if err != nil { }" form, it is clear that the possibility of error is
considered. However with the proposed "n, return = writer.Write(buf)" and $
styles, it's easy to miss the handling. A drastic change in control flow
like returning should always stand out in its own statement.
Thanks,
Josh
Post by Nigel Tao
Post by Ian Lance Taylor
One could say that
f, return = os.Create("filename")
was permitted
It's mostly academic at this point, but if we're brainstorming new
$ is an operator that can only be used inside a function (let's call
it f) that returns (ret0, ret1, ..., retN, error). Suppose g is a
function or method called inside f, and g(etc) would normally return
(a, b, err). $g(etc) would mean (a, b) if err is nil, otherwise f
returns (zero0, zero1, ..., zeroN, err).
n, err := fmt.Fprintf(w, "hello\n")
if err != nil {
return err
}
could become
n := $fmt.Fprintf(w, "hello\n")
and
func readAllZlib(r io.Reader) ([]byte, error) {
zr, err := zlib.NewReader(r)
if err != nil {
return nil, err
}
return ioutil.ReadAll(zr)
}
could become
func readAllZlib(r io.Reader) ([]byte, error) {
return ioutil.ReadAll($zlib.**NewReader(r))
}
I'm not sure if I actually like the idea. It does save some
if err != nil {
return nil, fmt.Errorf("http: error connecting to proxy %s: %v",
cm.proxyURL, err)
}
is more useful than
if err != nil {
return nil, err
}
--
--
--
650-335-5765
--
--
Michael T. Jones | Chief Technology Advocate | mtj-hpIqsD4AKlfQT0dZR+***@public.gmane.org | +1
650-335-5765

--
Scott Pakin
2012-09-26 19:33:28 UTC
Permalink
Okay, here's my riff on this theme: What if Go were to interpret &f = x,
where f is a function and x is an arbitrary value, as f(x)? What does that
have to do with exception handling? Well, we can use a func(error)—or in
some cases a func(bool)—to handle exceptional conditions:

myFile, &log.Fatal := os.Open("happy.txt")
data := make([]byte, 100)
count, &log.Fatal := myFile.Read(data)

*Advantages*: Exception handling is explicit. Different calls within the
same function can use either the same or different handlers. Handler has
the option of continuing the control flow or panicking to introduce
non-local control flow. Approach is not limited to just exceptions or just
functions returning an error as the exceptional value.

What do you think?

— Scott

--
Rémy Oudompheng
2012-09-26 19:39:22 UTC
Permalink
Post by Scott Pakin
Okay, here's my riff on this theme: What if Go were to interpret &f = x,
where f is a function and x is an arbitrary value, as f(x)? What does that
have to do with exception handling? Well, we can use a func(error)—or in
myFile, &log.Fatal := os.Open("happy.txt")
data := make([]byte, 100)
count, &log.Fatal := myFile.Read(data)
Advantages: Exception handling is explicit. Different calls within the same
function can use either the same or different handlers. Handler has the
option of continuing the control flow or panicking to introduce non-local
control flow. Approach is not limited to just exceptions or just functions
returning an error as the exceptional value.
What do you think?
It is already possible. See template.Must for example.

Rémy.

--
John Asmuth
2012-09-26 20:30:15 UTC
Permalink
Only possible if you write the function for the specific parameters
expected. This is much more general, if a bit wonky.

I really don't think the slight inconvenience here merits a change to the
language.
Post by Daniel Morsing
Post by Scott Pakin
Okay, here's my riff on this theme: What if Go were to interpret &f = x,
where f is a function and x is an arbitrary value, as f(x)? What does
that
Post by Scott Pakin
have to do with exception handling? Well, we can use a func(error)—or
in
Post by Scott Pakin
myFile, &log.Fatal := os.Open("happy.txt")
data := make([]byte, 100)
count, &log.Fatal := myFile.Read(data)
Advantages: Exception handling is explicit. Different calls within the
same
Post by Scott Pakin
function can use either the same or different handlers. Handler has the
option of continuing the control flow or panicking to introduce
non-local
Post by Scott Pakin
control flow. Approach is not limited to just exceptions or just
functions
Post by Scott Pakin
returning an error as the exceptional value.
What do you think?
It is already possible. See template.Must for example.
Rémy.
--
Kevin Gillette
2012-09-26 21:14:41 UTC
Permalink
The template.Must technique is limited since you have to make a specialized
function to handle each set returned types. If the community were to rally
around template.Must style handling, with a defer-recover to turn panics
back into regular errors, then it'd be beneficial to have a "magic" builtin
that takes any types on input, with the requirement that the last is a type
assignable to the builtin error interface, and then panics if err != nil,
or otherwise returns all but the error. For example:

func f() (err error) {
defer func() { err = recover() }()
// ...
line, isPrefix := errchk(bufioReader.ReadLine())
// ...
}

However, I rather dislike the idea of making panic an endorsed error
management mechanism.

As long as Ian is talking about changing the nature of labels, a thought I
had the other day, is along the same lines as errcheck, but instead takes a
label as the first parameter, but returns all the arguments, including the
error value:

func f(filename string) error {
line, isPrefix, err := errgoto(handle1, bufioReader.ReadLine())
info, err := errgoto(handle1, os.Stat(filename))
errgoto(handle2, sealBunker())
handle1:
return err
handle2:
panic(err)
}

the problems here, of course, are:

1) the parser would have to be able to treat identifiers in function params
as a label (without allowing an expression), which would require the
grammar to be modified.

2) the call mechanism would need to be given an exception for this builtin,
allowing all arguments _after_ the first to fit the existing f(g()) special
case.

3) it would be more trouble than it's worth since you'd have to either
declare most of your variables before any errgoto uses (same rules as goto
-- can't skip over declarations), or you'd have to be excessive use of
anonymous blocks, or declaration hoisting would have to be added to the
language.

Suffice it to say, it's an idea, but I don't much like that either. I'm
pretty happy with doing if/else chains anyway -- the ability to do
assignments in the pertinent control structures makes this pleasant enough.

I think Ian's idea is 'neat' from a technical perspective, but is perhaps
swaying a bit towards the dark side (since control flow would be magic --
it's a bit like "come from").
Post by Daniel Morsing
Post by Scott Pakin
Okay, here's my riff on this theme: What if Go were to interpret &f = x,
where f is a function and x is an arbitrary value, as f(x)? What does
that
Post by Scott Pakin
have to do with exception handling? Well, we can use a func(error)—or
in
Post by Scott Pakin
myFile, &log.Fatal := os.Open("happy.txt")
data := make([]byte, 100)
count, &log.Fatal := myFile.Read(data)
Advantages: Exception handling is explicit. Different calls within the
same
Post by Scott Pakin
function can use either the same or different handlers. Handler has the
option of continuing the control flow or panicking to introduce
non-local
Post by Scott Pakin
control flow. Approach is not limited to just exceptions or just
functions
Post by Scott Pakin
returning an error as the exceptional value.
What do you think?
It is already possible. See template.Must for example.
Rémy.
--
Dan Kortschak
2012-09-26 21:30:49 UTC
Permalink
I'm pretty sure this has been suggested in the past.
Post by Kevin Gillette
The template.Must technique is limited since you have to make a specialized
function to handle each set returned types. If the community were to rally
around template.Must style handling, with a defer-recover to turn panics
back into regular errors, then it'd be beneficial to have a "magic" builtin
that takes any types on input, with the requirement that the last is a type
assignable to the builtin error interface, and then panics if err != nil,
func f() (err error) {
defer func() { err = recover() }()
// ...
line, isPrefix := errchk(bufioReader.ReadLine())
// ...
}
--
Gustavo Niemeyer
2012-09-25 13:08:57 UTC
Permalink
Post by Michael Jones
One positive point about exceptions: it is nice to have the "happy case"
code flow be clean.
(...)
Post by Michael Jones
* Error handling somewhere else so that the logic of the algorithm is
expressed purely and not obscured by a crowd of real-world constraints and
possibile woes.
The happy case is when the code does what it should. Just because one
wants something to not happen doesn't make it less true nor less
important. It is very much part of the algorithm.

We have been teaching people otherwise for such a long time. No wonder
most software is so unstable.


gustavo @ http://niemeyer.net

--
Ben J
2012-09-26 16:18:09 UTC
Permalink
Do we really want people to adopt Go who are so against a fundamental
part of the language? I think Go is popular enough now where the Go
community shouldn't have to convince people to try it.

It's great if you think Python|Ruby|C++|etc is better than Go. Write
your code in your preferred language, solve real world problems, and
be happy. Think of all the time we're all wasting reading and
replying to this thread rather than improving software.
Post by Patrick Mylund Nielsen
What DisposaBoy was pointing out is that your original post basically read,
"Your error handling sucks! Some other guys said that your error handling
sucks. Why does it suck? Too bad, now I won't use your language", and it
was obvious that you haven't actually used the language yourself. You need
to use the language, or at least study (more) code written in it, before
you adopt and parrot somebody else's opinion, especially if you're going to
post such a condescending/derisive message to that language's mailing list.
Of course, that doesn't just apply to programming languages. Many
programmers use NoSQL databases to be able to make "web scale"
applications, and not RDBMS, even though they will likely be tens or
hundreds of times as productive using something relational, and won't
actually have the problems that Facebook has for messaging (they still use
MySQL for everything else)--and one of the major reasons they're using
these solutions is that Hacker News and reddit.com/r/programming are filled
with threads that worship the latest new thing and dismisses RDBMSs as "old
and bad" (when in reality they're some of the most mature pieces of
software that exist.) Now that Google has unveiled Spanner, maybe all the
programmers who made MongoDB applications will rave about ACID,
transactional consistency and the ease-of-use of query languages... :) (It
already exists I guess: "NewSQL".)
My/our point is: Don't dismiss something because someone got to #1 on
Hacker News criticizing it. In a lot of cases, they don't really know what
they're talking about, so adopting their (misinformed) opinion is doing
yourself a disfavor. NoSQL, or exceptions, may be right for you, but that
may be the case far less often than you'd think if you ingest Hacker News
articles uncritically. Try it, then make up your own mind.
Post by k***@public.gmane.org
@DisposaBoy I do have my opinions, I just pointed to a blog that summed
it up quite nicely. If you tell me to jump of a bridge, I will probably
push you off instead. You are the one spamming the list with your reply
devoid of content.  As you can see, there has been quite some interest in
my sololoquy.
Post by DisposaBoy
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.**com/2012/09/23/why-im-not-**
leaving-python-for-go/<http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-...>
http://www.yosefk.com/blog/**error-codes-vs-exceptions-**
critical-code-vs-typical-code.**html<http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs...>
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story.  I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
Form what you've said, it doesn't appear that you are able to form your
own opinions. What happens if I tell you that it's a good idea to go
jumping off bridges? ... In any case, please don't spam the list
 --
--
Kevin Gillette
2012-09-27 07:11:45 UTC
Permalink
Post by Ben J
Do we really want people to adopt Go who are so against a fundamental
part of the language? I think Go is popular enough now where the Go
community shouldn't have to convince people to try it.
It's great if you think Python|Ruby|C++|etc is better than Go. Write
your code in your preferred language, solve real world problems, and
be happy. Think of all the time we're all wasting reading and
replying to this thread rather than improving software.
I agree with this sentiment entirely, though I'll add that I believe Go is
popular because it didn't sacrifice its integrity in the name of popularity.

--
bryanturley
2012-09-24 20:04:08 UTC
Permalink
Beyond what everyone else has said already...
Just because something returns an error doesn't mean you have to check it.
Though you will probably wish you had at some point a day or 2 after
whatever your working on mysteriously stops though ;)
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to deal
with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
k***@public.gmane.org
2012-09-24 20:42:58 UTC
Permalink
@bryanturley Well, thats exactly the problem. If you fail to check it and
something breaks in 2 days, you won't have a clue of what happened. With
exceptions, you will know exactly what happened and exactly where and when.
Post by bryanturley
Beyond what everyone else has said already...
Just because something returns an error doesn't mean you have to check it.
Though you will probably wish you had at some point a day or 2 after
whatever your working on mysteriously stops though ;)
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
Rémy Oudompheng
2012-09-24 20:52:07 UTC
Permalink
Post by k***@public.gmane.org
@bryanturley Well, thats exactly the problem. If you fail to check it and
something breaks in 2 days, you won't have a clue of what happened. With
exceptions, you will know exactly what happened and exactly where and when.
Again, this is a programmer point of view. A user (programmer or not)
doesn't know much more about the problem when presented a stack trace.
In many programming styles, exceptions that are caught forget where
they happened (because the ugly stack trace is discarded) an when they
happened (such information is seldom recorded). In some situations
where you want to conceal the source code, you even don't want to show
it.

Rémy.

--
Jakub Labath
2012-09-25 14:30:04 UTC
Permalink
Exactly you say. Funny I do not see that in actual production code. As
someone who makes a living maintaining old software I see a lot of this.

try:
...30+ lines...
catch Exception as e:
print "Error occured", e

Yes they could print a stack trace in there but most "geniuses" never do.
So when the error is something like ValueError or IOError or NullPointer.
It's basically as useful as assigning all your go errors to _.
Actually it's even worse because when I see _ I know that i need to go in
and replace it with error handling. When I just see bunch of code I have no
idea which of the calls can throw an error.

| Exceptions might not be perfect, but are damn better than checking each
and every function call.

So my above example could be written like this in go,

func monsterFunction() (result string, err error){
if err = smallCallThatCanFail1(); err != nil {
return
}
if err = smallCallThatCanFail2(); err != nil {
return
}
.... and so on
result = "ALL OK"
return
}

And then deal with the error returned in the caller of the monsterFunction.
Is it more lines than an exception yes. But well worth the tradeoff in how
much more obvious it is to tell in go code what is going on.

Final thought when writing robust software I check every function that can
fail regardless of whether I use java, python or go. It slows you done
initially but it pays off big time much later.

In my opinion the go's error handling is one of the finest that I know.

Cheers
Post by k***@public.gmane.org
@bryanturley Well, thats exactly the problem. If you fail to check it
and something breaks in 2 days, you won't have a clue of what happened.
With exceptions, you will know exactly what happened and exactly where and
when.
Post by bryanturley
Beyond what everyone else has said already...
Just because something returns an error doesn't mean you have to check it.
Though you will probably wish you had at some point a day or 2 after
whatever your working on mysteriously stops though ;)
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
k***@public.gmane.org
2012-09-24 20:39:43 UTC
Permalink
Sorry for the unfriendly-flame-bate subject of original post, but I really
wanted the feedback of some passionate souls in the go community.
I still prefer (un-checked) exceptions (not perfect, by any means) than
return codes though.
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to deal
with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
ISockGo
2012-09-25 14:57:55 UTC
Permalink
Hello Mr Unknown :),

Go is a wonderful language. Every language has
it's own style and behavior, the bigest challenge for a languages is to
keep the memory and CPU down and provide the easy way to code it. Go came
up with a new way of writing code and using the OOPs, with the power of C
and code style like python. And the best part it gives you an executable
output which does not require any run time or virtual machine environment
to run the programme on different type of OS. The traditional OOPs and
try-catch methodologies are very memory consuming, specially
when programers don't know how to code it better and where to use what. The
most Java programs are memory consuming, you can check.

I think, that is the reason, Go came up with this old error handling
management.

Keep rocking Goians :)


Thanks,
Chuck
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to deal
with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
Nguyên Nguyễn Văn Cao
2012-09-25 15:06:04 UTC
Permalink
I'm not a professional programmer, the fact that I was a student.
All the benefits I found was that when you use exceptions you do not need
to declare an extra output parameter to handle errors. And in my point of
view, there is no big difference.
Here is how my teacher show me how to use exception:
try {
MaybeAnIssue();
} catch {
//do something else or safety quit
}
with Go:
err := MaybeAnIssue()
if err != nil {
//do something else or safety quit
}

So in Go way, we write some more code, but the idea is the same, is it
right?
Or with exception we don't need to check the if there is throwed exception?
Vào 22:55:57 UTC+7 Thứ hai, ngày 24 tháng chín năm 2012, (khÃŽng xác định)
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to deal
with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
Larry Clapp
2012-09-25 16:10:09 UTC
Permalink
It's funny. When I heard about Go, I went to golang.org and read through
the tour, and then went through it again and coded a lot of the problems in
it. And you know what: I decided I like Go. How did you form your opinion
about it? Tangentially, how much Go have you written?

If you don't like Go, great. More power to you. What was your motivation
for telling us so, and (in my opinion) so rudely, at that? Why should we
respond with anything more than a crisp, clear, "fuck you too"?

-- Larry
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to deal
with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
Steven Rice
2012-09-25 16:22:58 UTC
Permalink
I always enjoy your input Larry :). Also OP stated " I don't want to check
every freaking single function invocation for errors. " Go actually allows
you to do this, languages that throw exceptions do not. In Go the worst
thing that happens if you ignore an error is unexpected behavior. In
exception throwing languages, if you ignore the exception then your program
crashes.
Post by Larry Clapp
It's funny. When I heard about Go, I went to golang.org and read through
the tour, and then went through it again and coded a lot of the problems in
it. And you know what: I decided I like Go. How did you form your opinion
about it? Tangentially, how much Go have you written?
If you don't like Go, great. More power to you. What was your motivation
for telling us so, and (in my opinion) so rudely, at that? Why should we
respond with anything more than a crisp, clear, "fuck you too"?
-- Larry
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
Larry Clapp
2012-09-25 16:51:07 UTC
Permalink
Awesome. :)

Just for the record: None of those question were rhetorical. I'm curious
about the answer to all of them. (Which should not be interpreted to mean
I demand or believe that I deserve or am owed an answer, either. The OP
may answer or not, as s/he wishes. I'm just curious.)

-- L
Post by Steven Rice
I always enjoy your input Larry :). Also OP stated " I don't want to check
every freaking single function invocation for errors. " Go actually allows
you to do this, languages that throw exceptions do not. In Go the worst
thing that happens if you ignore an error is unexpected behavior. In
exception throwing languages, if you ignore the exception then your program
crashes.
Post by Larry Clapp
It's funny. When I heard about Go, I went to golang.org and read
through the tour, and then went through it again and coded a lot of the
problems in it. And you know what: I decided I like Go. How did you form
your opinion about it? Tangentially, how much Go have you written?
If you don't like Go, great. More power to you. What was your
motivation for telling us so, and (in my opinion) so rudely, at that? Why
should we respond with anything more than a crisp, clear, "fuck you too"?
-- Larry
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
Ziad Hatahet
2012-09-25 19:34:59 UTC
Permalink
I would take a crash over unexpected/undefined behavior.

--
Ziad
Post by Steven Rice
I always enjoy your input Larry :). Also OP stated " I don't want to check
every freaking single function invocation for errors. " Go actually allows
you to do this, languages that throw exceptions do not. In Go the worst
thing that happens if you ignore an error is unexpected behavior. In
exception throwing languages, if you ignore the exception then your program
crashes.
Post by Larry Clapp
It's funny. When I heard about Go, I went to golang.org and read
through the tour, and then went through it again and coded a lot of the
problems in it. And you know what: I decided I like Go. How did you form
your opinion about it? Tangentially, how much Go have you written?
If you don't like Go, great. More power to you. What was your
motivation for telling us so, and (in my opinion) so rudely, at that? Why
should we respond with anything more than a crisp, clear, "fuck you too"?
-- Larry
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.**com/2012/09/23/why-im-not-**
leaving-python-for-go/<http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/>
http://www.yosefk.com/blog/**error-codes-vs-exceptions-**
critical-code-vs-typical-code.**html<http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html>
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
--
Steven Rice
2012-09-25 19:39:30 UTC
Permalink
The user would rather not see either of them, so you could just check all
your errors anyways. It is good programming to do so. The OP was
complaining that Go forced error checking when this isn't true though.
Post by Ziad Hatahet
I would take a crash over unexpected/undefined behavior.
--
Ziad
Post by Steven Rice
I always enjoy your input Larry :). Also OP stated " I don't want to
check every freaking single function invocation for errors. " Go actually
allows you to do this, languages that throw exceptions do not. In Go the
worst thing that happens if you ignore an error is unexpected behavior. In
exception throwing languages, if you ignore the exception then your program
crashes.
Post by Larry Clapp
It's funny. When I heard about Go, I went to golang.org and read
through the tour, and then went through it again and coded a lot of the
problems in it. And you know what: I decided I like Go. How did you form
your opinion about it? Tangentially, how much Go have you written?
If you don't like Go, great. More power to you. What was your
motivation for telling us so, and (in my opinion) so rudely, at that? Why
should we respond with anything more than a crisp, clear, "fuck you too"?
-- Larry
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.**com/2012/09/23/why-im-not-**
leaving-python-for-go/<http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/>
http://www.yosefk.com/blog/**error-codes-vs-exceptions-**
critical-code-vs-typical-code.**html<http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html>
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
--
Patrick Mylund Nielsen
2012-09-25 19:40:43 UTC
Permalink
It's unexpected behavior (to the programmer), not undefined behavior. Also,
this only happens if you both ignore the returned error value, and if the
other return value(s) in whatever form they were returned aren't sufficien
(which is usually the case.)

So, you only get unexpected behavior if you do:

foo, _ := Foo()
// no if err != nil { ... }

that's why that's frowned upon.

(In most cases, the unexpected behavior will be a nil pointer dereference,
so you do get the exception/panic and stack trace, anyway.)
Post by Ziad Hatahet
I would take a crash over unexpected/undefined behavior.
--
Ziad
Post by Steven Rice
I always enjoy your input Larry :). Also OP stated " I don't want to
check every freaking single function invocation for errors. " Go actually
allows you to do this, languages that throw exceptions do not. In Go the
worst thing that happens if you ignore an error is unexpected behavior. In
exception throwing languages, if you ignore the exception then your program
crashes.
Post by Larry Clapp
It's funny. When I heard about Go, I went to golang.org and read
through the tour, and then went through it again and coded a lot of the
problems in it. And you know what: I decided I like Go. How did you form
your opinion about it? Tangentially, how much Go have you written?
If you don't like Go, great. More power to you. What was your
motivation for telling us so, and (in my opinion) so rudely, at that? Why
should we respond with anything more than a crisp, clear, "fuck you too"?
-- Larry
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.**com/2012/09/23/why-im-not-**
leaving-python-for-go/<http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/>
http://www.yosefk.com/blog/**error-codes-vs-exceptions-**
critical-code-vs-typical-code.**html<http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html>
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
--
--
k***@public.gmane.org
2012-09-25 17:40:06 UTC
Permalink
Post by Larry Clapp
It's funny. When I heard about Go, I went to golang.org and read through
the tour, and then went through it again and coded a lot of the problems in
it. And you know what: I decided I like Go. How did you form your opinion
about it?
I do like go. I also read the tour and bought a book.

Tangentially, how much Go have you written?
Very, very little. I made this post while fiddling with a piece of code
that dind't do anything. Nothing got printed, no error reported, nada. How
on earth am I supposed to start troubleshooting the damn thing. With
exceptions, I will have a nice stacktrace that will pinpoint exactly where
I messed up.

If you don't like Go, great. More power to you. What was your motivation
Post by Larry Clapp
for telling us so, and (in my opinion) so rudely, at that? Why should we
respond with anything more than a crisp, clear, "fuck you too"?
Sorry for the rude post, I have already aknowledged that. It was also on
purpose, because I knew it would get more attention...
Post by Larry Clapp
-- Larry
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
Patrick Mylund Nielsen
2012-09-25 18:08:40 UTC
Permalink
I made this post while fiddling with a piece of code that dind't do
anything. Nothing got printed, no error reported, nada. How on earth am I
supposed to start troubleshooting the damn thing. With exceptions, I will
have a nice stacktrace that will pinpoint exactly where I messed up.

That sounds very strange, especially since each error value will include
specific information if there was an error. Can you show your code?
http://play.golang.org/ -> Share
Post by Larry Clapp
It's funny. When I heard about Go, I went to golang.org and read
through the tour, and then went through it again and coded a lot of the
problems in it. And you know what: I decided I like Go. How did you form
your opinion about it?
I do like go. I also read the tour and bought a book.
Tangentially, how much Go have you written?
Very, very little. I made this post while fiddling with a piece of code
that dind't do anything. Nothing got printed, no error reported, nada. How
on earth am I supposed to start troubleshooting the damn thing. With
exceptions, I will have a nice stacktrace that will pinpoint exactly where
I messed up.
If you don't like Go, great. More power to you. What was your motivation
Post by Larry Clapp
for telling us so, and (in my opinion) so rudely, at that? Why should we
respond with anything more than a crisp, clear, "fuck you too"?
Sorry for the rude post, I have already aknowledged that. It was also on
purpose, because I knew it would get more attention...
Post by Larry Clapp
-- Larry
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.**com/2012/09/23/why-im-not-**
leaving-python-for-go/<http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/>
http://www.yosefk.com/blog/**error-codes-vs-exceptions-**
critical-code-vs-typical-code.**html<http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html>
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
--
Steven Rice
2012-09-25 18:14:23 UTC
Permalink
Can only happen in a semantic error and that will be exactly the same in
any language you ever use. If it is a compiler error, you will see the
error.
Post by Larry Clapp
Tangentially, how much Go have you written?
Very, very little. I made this post while fiddling with a piece of code
that dind't do anything. Nothing got printed, no error reported, nada. How
on earth am I supposed to start troubleshooting the damn thing. With
exceptions, I will have a nice stacktrace that will pinpoint exactly where
I messed up.
--
Larry Clapp
2012-09-25 18:42:33 UTC
Permalink
Well, you know, you could've just said "I'm having trouble with this code;
I expect X and get Y." Have you ever read How To Ask Questions The Smart
Way <http://www.catb.org/esr/faqs/smart-questions.html>?

It was also on purpose, because I knew it would get more attention...


Ah <http://en.wikipedia.org/wiki/The_Boy_Who_Cried_Wolf>.

-- L
Post by k***@public.gmane.org
Post by Larry Clapp
It's funny. When I heard about Go, I went to golang.org and read
through the tour, and then went through it again and coded a lot of the
problems in it. And you know what: I decided I like Go. How did you form
your opinion about it?
I do like go. I also read the tour and bought a book.
Tangentially, how much Go have you written?
Very, very little. I made this post while fiddling with a piece of code
that dind't do anything. Nothing got printed, no error reported, nada. How
on earth am I supposed to start troubleshooting the damn thing. With
exceptions, I will have a nice stacktrace that will pinpoint exactly where
I messed up.
If you don't like Go, great. More power to you. What was your motivation
Post by Larry Clapp
for telling us so, and (in my opinion) so rudely, at that? Why should we
respond with anything more than a crisp, clear, "fuck you too"?
Sorry for the rude post, I have already aknowledged that. It was also on
purpose, because I knew it would get more attention...
Post by Larry Clapp
-- Larry
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
Steven Rice
2012-09-25 18:33:40 UTC
Permalink
Also as I replied to the article on keeping Python vs. Go: that article
complains about lower level error handling, not Go itself. I don't think
high level programming or Python are bad. In fact I rather enjoy Python. I
do think however that Go handles problems that Python does not handle well
and that Go can handle Pythons problem domain with better performance
(Although it may not be as quick to code all the string parsing in Go)
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to deal
with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
d***@public.gmane.org
2012-09-25 14:42:46 UTC
Permalink
This kind of error handling is the best part of Go.
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to deal
with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
i***@public.gmane.org
2012-09-26 02:16:39 UTC
Permalink
The first blog post makes valid points - it doesn't take much go
programming practice to realise that the go error type is 'unflavoured'.. I
don't think that makes it necessarily suck - the way I write it encourages
me to create "self documenting code" - where error checks do a lot of the
work of replacing inline comments. I also appreciate the ability to not
error check - though this generally trips me up even on trivial code.

Also I think "check every function call" is exaggeration - mostly error
checking mostly only needs doing on processes with uncertain outcomes - eg
disk access, user input etc - algorithmic code not so much or not at all.
I'm not convinced there is more error checking to do than in other
languages - a try-catch block has a few less "if" statements (not many
keystrokes) - but there's still the cleaning up to do - it's just moved to
the end of a block, instead of immediate to the statement.

I have to admit at times I've noticed typing "if err!= nil { blah ..}" a
lot of times - but only for certain program blocks - it wasn't a big issue

Whilst on the topic of errors I'd like to digress and suggest there are
other sucky bits with errors:
*The basic issue is checking an error returned (from a standard package, or
other) against a known error - the issue is - there are no guidlines, and
implementation seem easy to break. - examples and exposition
**One part solution that is that packages should define all error returns
as constants - problematic when wanting to write errors that contain
contect info.
**the issue of "what error is it" -eg in image/jpeg
http://golang.org/pkg/image/jpeg/ - if I'm using jpeg.Decode there might be
an error - ok - what is it ? - I have to dig into the source to find out..
If I wan't to compare that error I have to type the string as a perfect
match - this feels half assed, and there's little to stop this breaking
later if the package changes.. It suggests there could be a need for error
codes in addition to the string - possibly a slice of codes (with an empty
slice for those that can't be bothered) - this could get messy quickly -
but I think people will appreciate the issue - comparing strings seems just
too easy to break - maybe there is good way to do this?
**I see that some packages do something along these lines eg
http://golang.org/pkg/os/#pkg-variables - also
http://golang.org/pkg/os/#PathError - this implementation seems to be an
answer - would this be a self submit and is it really needed/would be
accepted - maybe some sort of agreement on the cross package standards for
struct fields and names for an struct type implementing the error interface
should be got first ?? I'd definately like to seem somthing like this on
other packages
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to deal
with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
Zizon Qiu
2012-09-26 04:46:55 UTC
Permalink
IMO,one prefer try-catch over error code could use the panic/defer/recover
pattern in Go.
such that instead of the normal try-catch

try {
doSomething();
}catch( Exception e){
handleException(e);
}

doing like this,

doSomething() // use panic instead of throw exception
defer catch(){
if r := recover(); r != nil{
// here r is the panic context,we SHOULD know which panic it exactly is.
// and we can "resume" the control flow like the normal try-catch using
necessary clause.
}
}()
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to deal
with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
--
p***@public.gmane.org
2012-09-26 05:59:26 UTC
Permalink
Why not get the best of both (off the top of my head):

If you assign the error to a variable, then business as usual (the Go
way), e.g.:

if err := sealPresidentialBunker(); err != nil {
return "oops";
}
triggerDoomsdayDevice();

If you don't assign the error, then the compiler could switch to standard
exception semantics, e.g.:

sealPresidentialBunker(); // <-- Since not assigning error, an exception
would be thrown
triggerDoomsdayDevice();

This way you get both worlds.
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to deal
with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
Dave Cheney
2012-09-26 06:48:06 UTC
Permalink
Received: by 10.50.209.9 with SMTP id mi9mr5634258igc.5.1348642089248;
Tue, 25 Sep 2012 23:48:09 -0700 (PDT)
X-BeenThere: golang-nuts-/***@public.gmane.org
Received: by 10.50.5.208 with SMTP id u16ls7486243igu.1.canary; Tue, 25 Sep
2012 23:48:07 -0700 (PDT)
Received: by 10.50.36.199 with SMTP id s7mr5595429igj.3.1348642087346;
Tue, 25 Sep 2012 23:48:07 -0700 (PDT)
Received: by 10.50.36.199 with SMTP id s7mr5595428igj.3.1348642087333;
Tue, 25 Sep 2012 23:48:07 -0700 (PDT)
Received: from mail-oa0-f45.google.com (mail-oa0-f45.google.com [209.85.219.45])
by gmr-mx.google.com with ESMTPS id us14si327825igb.3.2012.09.25.23.48.07
(version=TLSv1/SSLv3 cipher=OTHER);
Tue, 25 Sep 2012 23:48:07 -0700 (PDT)
Received-SPF: neutral (google.com: 209.85.219.45 is neither permitted nor denied by best guess record for domain of dave-7L4Cwp9BzA+sTnJN9+***@public.gmane.org) client-ip=209.85.219.45;
Received: by oagi18 with SMTP id i18so342889oag.32
for <golang-nuts-/***@public.gmane.org>; Tue, 25 Sep 2012 23:48:06 -0700 (PDT)
Received: by 10.60.1.106 with SMTP id 10mr14775472oel.84.1348642086776; Tue,
25 Sep 2012 23:48:06 -0700 (PDT)
Received: by 10.76.69.69 with HTTP; Tue, 25 Sep 2012 23:48:06 -0700 (PDT)
In-Reply-To: <1cac7eac-670e-4750-9c1d-281cbf635184-/***@public.gmane.org>
X-Gm-Message-State: ALoCoQloFxCMA826WGeTauSiyw6W8KWJmW/KkkS969cCrgHieWpawtjuxlXXspep8UK3kI60QYwc
X-Original-Sender: dave-7L4Cwp9BzA+sTnJN9+***@public.gmane.org
X-Original-Authentication-Results: gmr-mx.google.com; spf=neutral (google.com:
209.85.219.45 is neither permitted nor denied by best guess record for domain
of dave-7L4Cwp9BzA+sTnJN9+***@public.gmane.org) smtp.mail=dave-7L4Cwp9BzA+sTnJN9+***@public.gmane.org
Precedence: list
Mailing-list: list golang-nuts-/***@public.gmane.org; contact golang-nuts+owners-/***@public.gmane.org
List-ID: <golang-nuts.googlegroups.com>
X-Google-Group-Id: 332403668183
List-Post: <http://groups.google.com/group/golang-nuts/post?hl=en-US>, <mailto:golang-nuts-/***@public.gmane.org>
List-Help: <http://groups.google.com/support/?hl=en-US>, <mailto:golang-nuts+help-/***@public.gmane.org>
List-Archive: <http://groups.google.com/group/golang-nuts?hl=en-US>
Sender: golang-nuts-/***@public.gmane.org
List-Subscribe: <http://groups.google.com/group/golang-nuts/subscribe?hl=en-US>,
<mailto:golang-nuts+subscribe-/***@public.gmane.org>
List-Unsubscribe: <http://groups.google.com/group/golang-nuts/subscribe?hl=en-US>,
<mailto:googlegroups-manage+332403668183+unsubscribe-/***@public.gmane.org>
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.go.general/72490>

I'd afraid this example falls foul here

fmt.Println("Goodbye cruel world") // maybe should panic if whatever
os.Stdout was pointing too at the time failed to write, maybe

file.Close() // should this panic ? really ? what do you want to do if
you can't _close_ a file descriptor ?
If you assign the error to a variable, then business as usual (the Go way),
if err := sealPresidentialBunker(); err != nil {
return "oops";
}
triggerDoomsdayDevice();
If you don't assign the error, then the compiler could switch to standard
sealPresidentialBunker(); // <-- Since not assigning error, an exception
would be thrown
triggerDoomsdayDevice();
This way you get both worlds.
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to deal
with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
--
cary-6STWZtX7tXBWk0Htik3J/
2012-09-26 18:48:57 UTC
Permalink
Have you considered laying out the rules in an interactive decision table
processor, check out LogicGem at http://www.catalyst.com/products/logicgem/
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to deal
with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
k***@public.gmane.org
2012-09-27 04:33:52 UTC
Permalink
Ok, here is a dumbded down example of what I mean:

package main

import (
"bufio"
"os"
)

func main() {
file, _ := os.OpenFile("/nowhere/", os.O_WRONLY|os.O_CREATE, 0666)
writer := bufio.NewWriter(file);
writer.WriteString("foobar\n")
}

Run this, and what will you get? Nothing. No error, no stacktrace ...
absolutely nothing. Nada.

I know that programers should check the error codes and should be super
smart, and should have tests for their code, and should not have deadlines,
and should be handsome ... but in reality, well you have been there.
This applies to any error handling mechanism error codes, exceptions or you
name it... as someone mentioned Go (or any language) will not do the error
checking, the programmer will.
So when the programmer, god forbid, fails to do his job I would rather have
a180 line stacktrace pinpointing me where the stupid programmer messed up.
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to deal
with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
Patrick Mylund Nielsen
2012-09-27 04:41:11 UTC
Permalink
This is a silly argument, IMO. Just check the error values. If you are
actively ignoring them you are doing the equivalent of try: foo; except:
pass.
Post by k***@public.gmane.org
package main
import (
"bufio"
"os"
)
func main() {
file, _ := os.OpenFile("/nowhere/", os.O_WRONLY|os.O_CREATE, 0666)
writer := bufio.NewWriter(file);
writer.WriteString("foobar\n")
}
Run this, and what will you get? Nothing. No error, no stacktrace ...
absolutely nothing. Nada.
I know that programers should check the error codes and should be super
smart, and should have tests for their code, and should not have deadlines,
and should be handsome ... but in reality, well you have been there.
This applies to any error handling mechanism error codes, exceptions or
you name it... as someone mentioned Go (or any language) will not do the
error checking, the programmer will.
So when the programmer, god forbid, fails to do his job I would rather
have a180 line stacktrace pinpointing me where the stupid programmer messed
up.
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.**com/2012/09/23/why-im-not-**
leaving-python-for-go/<http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/>
http://www.yosefk.com/blog/**error-codes-vs-exceptions-**
critical-code-vs-typical-code.**html<http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html>
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
--
k***@public.gmane.org
2012-09-27 05:04:43 UTC
Permalink
By the way, here is the same dumbed down version in Java:

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;

public class Foo {
public static void main(String[] args) throws Exception {
File file = new File("/nowhere/");
OutputStreamWriter writer = new OutputStreamWriter(new
FileOutputStream(file));
writer.write("foobar\n");
}
}

And what do you get? A nice stacktrace pinpointing the problem.

Exception in thread "main" java.io.FileNotFoundException: /nowhere/ (No
such file or directory)
at java.io.FileOutputStream.open(Native Method)
at java.io.FileOutputStream.<init>(FileOutputStream.java:194)
at java.io.FileOutputStream.<init>(FileOutputStream.java:145)
at Foo.main(Foo.java:8)
Post by k***@public.gmane.org
package main
import (
"bufio"
"os"
)
func main() {
file, _ := os.OpenFile("/nowhere/", os.O_WRONLY|os.O_CREATE, 0666)
writer := bufio.NewWriter(file);
writer.WriteString("foobar\n")
}
Run this, and what will you get? Nothing. No error, no stacktrace ...
absolutely nothing. Nada.
I know that programers should check the error codes and should be super
smart, and should have tests for their code, and should not have deadlines,
and should be handsome ... but in reality, well you have been there.
This applies to any error handling mechanism error codes, exceptions or
you name it... as someone mentioned Go (or any language) will not do the
error checking, the programmer will.
So when the programmer, god forbid, fails to do his job I would rather
have a180 line stacktrace pinpointing me where the stupid programmer messed
up.
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
Dave Cheney
2012-09-27 05:08:24 UTC
Permalink
Received: by 10.50.212.35 with SMTP id nh3mr201698igc.1.1348722507687;
Wed, 26 Sep 2012 22:08:27 -0700 (PDT)
X-BeenThere: golang-nuts-/***@public.gmane.org
Received: by 10.50.51.234 with SMTP id n10ls9994891igo.3.canary; Wed, 26 Sep
2012 22:08:25 -0700 (PDT)
Received: by 10.50.15.231 with SMTP id a7mr1425282igd.5.1348722505439;
Wed, 26 Sep 2012 22:08:25 -0700 (PDT)
Received: by 10.50.15.231 with SMTP id a7mr1425281igd.5.1348722505430;
Wed, 26 Sep 2012 22:08:25 -0700 (PDT)
Received: from mail-oa0-f53.google.com (mail-oa0-f53.google.com [209.85.219.53])
by gmr-mx.google.com with ESMTPS id ba5si1978420igb.3.2012.09.26.22.08.25
(version=TLSv1/SSLv3 cipher=OTHER);
Wed, 26 Sep 2012 22:08:25 -0700 (PDT)
Received-SPF: neutral (google.com: 209.85.219.53 is neither permitted nor denied by best guess record for domain of dave-7L4Cwp9BzA+sTnJN9+***@public.gmane.org) client-ip=209.85.219.53;
Received: by oagj6 with SMTP id j6so1603570oag.26
for <golang-nuts-/***@public.gmane.org>; Wed, 26 Sep 2012 22:08:25 -0700 (PDT)
Received: by 10.60.12.103 with SMTP id x7mr2136743oeb.142.1348722504989; Wed,
26 Sep 2012 22:08:24 -0700 (PDT)
Received: by 10.76.69.69 with HTTP; Wed, 26 Sep 2012 22:08:24 -0700 (PDT)
In-Reply-To: <e4e2f741-e4b1-47f6-a795-9fb556e6b4ed-/***@public.gmane.org>
X-Gm-Message-State: ALoCoQkPHFS566qcqR1l4bwurY0O7yqEDOjnwp3xpasVKxTmXGq32C3S6YWnEoKILYTNI5Fd3egv
X-Original-Sender: dave-7L4Cwp9BzA+sTnJN9+***@public.gmane.org
X-Original-Authentication-Results: gmr-mx.google.com; spf=neutral (google.com:
209.85.219.53 is neither permitted nor denied by best guess record for domain
of dave-7L4Cwp9BzA+sTnJN9+***@public.gmane.org) smtp.mail=dave-7L4Cwp9BzA+sTnJN9+***@public.gmane.org
Precedence: list
Mailing-list: list golang-nuts-/***@public.gmane.org; contact golang-nuts+owners-/***@public.gmane.org
List-ID: <golang-nuts.googlegroups.com>
X-Google-Group-Id: 332403668183
List-Post: <http://groups.google.com/group/golang-nuts/post?hl=en-US>, <mailto:golang-nuts-/***@public.gmane.org>
List-Help: <http://groups.google.com/support/?hl=en-US>, <mailto:golang-nuts+help-/***@public.gmane.org>
List-Archive: <http://groups.google.com/group/golang-nuts?hl=en-US>
Sender: golang-nuts-/***@public.gmane.org
List-Subscribe: <http://groups.google.com/group/golang-nuts/subscribe?hl=en-US>,
<mailto:golang-nuts+subscribe-/***@public.gmane.org>
List-Unsubscribe: <http://groups.google.com/group/golang-nuts/subscribe?hl=en-US>,
<mailto:googlegroups-manage+332403668183+unsubscribe-/***@public.gmane.org>
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.go.general/72630>

With respect, your translation is incorrect, If you were to ignore the
error in Java, as you had in Go you would have arrived at

public class Foo {
public static void main(String[] args) {
try {
File file = new File("/nowhere/");
OutputStreamWriter writer = new OutputStreamWriter(new
FileOutputStream(file));
writer.write("foobar\n");
} catch (Exception e) { // ignored }
}
}

--
Jesse McNelis
2012-09-27 05:48:21 UTC
Permalink
Post by k***@public.gmane.org
public class Foo {
public static void main(String[] args) throws Exception {
File file = new File("/nowhere/");
OutputStreamWriter writer = new OutputStreamWriter(new
FileOutputStream(file));
writer.write("foobar\n");
}
}
You couldn't argue that the Go code you posted was correct because
it's obviously not.
But it's often argued that this Java code is, because some other code
will do the error handling or the user will get a completely useless
stack trace (and thus the error is 'handled')
So developers write large amounts of code without any error handling
and nobody ever actually handles the errors.
Eventually the errors bubble up to the top of the stack where there is
no longer any context to do error handling and the best you can do is
log them and restart.

Because throwing errors from your APIs becomes such a low code
overhead (if you don't do any handling) more and more APIs start
throwing errors as they don't feel a need to minimise this because
people not handling errors don't feel the pain which makes it much
more of a pain for those writing good code.

Look at Java/Python/Ruby APIs they all throw exceptions for silly
reasons and most code doesn't bother handling any of them. Trying to
write correct python code that actually handles errors is largely an
impossibility in any code base of reasonable scale.

Go makes the error checking a little more error prone in an attempt at
making errors more visible to encourage programmers to actually
properly handle and think about them.
--
=====================
http://jessta.id.au

--
Nigel Tao
2012-09-27 06:09:59 UTC
Permalink
Post by Jesse McNelis
Trying to
write correct python code that actually handles errors is largely an
impossibility in any code base of reasonable scale.
I came across http://www.python.org/dev/peps/pep-0380/ the other day.
I am not a fluent Python programmer, so this may be unfair, but I find
the handles-exceptions-correctly code that follows "The statement
RESULT = yield from EXPR is semantically equivalent to" to be very
difficult to understand.

--
Dan Kortschak
2012-09-27 05:15:07 UTC
Permalink
Similarly, I have found that people who drive with their eyes closed
tend to have car accidents.

If you actively ignore the error return as you have, yes, you will have
problems. Now if you were talking about single return functions that
return errors and can be ignored without an explicit discard, there
might be a little more validity to your point.
Post by k***@public.gmane.org
package main
import (
"bufio"
"os"
)
func main() {
file, _ := os.OpenFile("/nowhere/", os.O_WRONLY|os.O_CREATE, 0666)
writer := bufio.NewWriter(file);
writer.WriteString("foobar\n")
}
Run this, and what will you get? Nothing. No error, no stacktrace ...
absolutely nothing. Nada.
I know that programers should check the error codes and should be super
smart, and should have tests for their code, and should not have deadlines,
and should be handsome ... but in reality, well you have been there.
This applies to any error handling mechanism error codes, exceptions or you
name it... as someone mentioned Go (or any language) will not do the error
checking, the programmer will.
So when the programmer, god forbid, fails to do his job I would rather have
a180 line stacktrace pinpointing me where the stupid programmer messed up.
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to deal
with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
Dumitru Ungureanu
2012-09-27 06:14:39 UTC
Permalink
file, _ := os.OpenFile("/nowhere/", os.O_WRONLY|os.O_CREATE, 0666)

Well then, I suppose this means this thread's title should read: "My Go
Error Handling Sucks" instead, no?

--
Larry Clapp
2012-09-27 10:27:11 UTC
Permalink
I remain unconvinced. You might as well say

-- perl --
open( OUT, ">/nowhere/" );
print OUT "foobar\n";
-- /perl --

It's just as stupid and just as wrong.

And I find your later Java code equally unconvincing. I find it pretty
crazy that "file not found" throws an exception. I'm sure this argument
has been made thousands of times, but that just doesn't seem like something
very exceptional to me. I also agree with Dave Cheney that your Java
translation is inaccurate. From that point of view, Go allows you to
ignore the error much less verbosely!

I guess, bottom line, Go gives you a little more rope than Java does. It's
like C or Perl in that particular sense. If you want to write Go, I think
you have two choices: you can establish better habits, or you can write a
library that panics in all the places you consider appropriate. (But, ew.)

I won't tell you that if you write more Go you'll learn to love it, or even
like it. (You *might,* but I won't say you *will*.) But I do think that
if you like the rest of the language, like the goroutines and channels,
then have at it, and grin and bear it on this particular issue. Frankly, I
bet if you think about it, you'll find some things that Java sucks at that
Go excels at.

-- Larry
Post by k***@public.gmane.org
package main
import (
"bufio"
"os"
)
func main() {
file, _ := os.OpenFile("/nowhere/", os.O_WRONLY|os.O_CREATE, 0666)
writer := bufio.NewWriter(file);
writer.WriteString("foobar\n")
}
Run this, and what will you get? Nothing. No error, no stacktrace ...
absolutely nothing. Nada.
I know that programers should check the error codes and should be super
smart, and should have tests for their code, and should not have deadlines,
and should be handsome ... but in reality, well you have been there.
This applies to any error handling mechanism error codes, exceptions or
you name it... as someone mentioned Go (or any language) will not do the
error checking, the programmer will.
So when the programmer, god forbid, fails to do his job I would rather
have a180 line stacktrace pinpointing me where the stupid programmer messed
up.
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
Raph
2012-09-27 10:35:08 UTC
Permalink
+1
Post by Larry Clapp
I remain unconvinced. You might as well say
-- perl --
open( OUT, ">/nowhere/" );
print OUT "foobar\n";
-- /perl --
It's just as stupid and just as wrong.
And I find your later Java code equally unconvincing. I find it pretty
crazy that "file not found" throws an exception. I'm sure this argument
has been made thousands of times, but that just doesn't seem like something
very exceptional to me. I also agree with Dave Cheney that your Java
translation is inaccurate. From that point of view, Go allows you to
ignore the error much less verbosely!
I guess, bottom line, Go gives you a little more rope than Java does.
It's like C or Perl in that particular sense. If you want to write Go, I
think you have two choices: you can establish better habits, or you can
write a library that panics in all the places you consider appropriate.
(But, ew.)
I won't tell you that if you write more Go you'll learn to love it, or
even like it. (You *might,* but I won't say you *will*.) But I do think
that if you like the rest of the language, like the goroutines and
channels, then have at it, and grin and bear it on this particular issue.
Frankly, I bet if you think about it, you'll find some things that Java
sucks at that Go excels at.
-- Larry
Post by k***@public.gmane.org
package main
import (
"bufio"
"os"
)
func main() {
file, _ := os.OpenFile("/nowhere/", os.O_WRONLY|os.O_CREATE, 0666)
writer := bufio.NewWriter(file);
writer.WriteString("foobar\n")
}
Run this, and what will you get? Nothing. No error, no stacktrace ...
absolutely nothing. Nada.
I know that programers should check the error codes and should be super
smart, and should have tests for their code, and should not have deadlines,
and should be handsome ... but in reality, well you have been there.
This applies to any error handling mechanism error codes, exceptions or
you name it... as someone mentioned Go (or any language) will not do the
error checking, the programmer will.
So when the programmer, god forbid, fails to do his job I would rather
have a180 line stacktrace pinpointing me where the stupid programmer messed
up.
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
Dumitru Ungureanu
2012-09-27 12:53:37 UTC
Permalink
package main

import (

"os"

)

func main() {

file := "/nowhere/"

text := "Prone to error"

print(writeToFile(file, text), "\n")

file = "here.txt"

text = "This might just work"

print(writeToFile(file, text), "\n")

}

// writeToFile takes two string arguments

// a file name and a string to write to that file

// and returns an error string for the write operation

func writeToFile(f, s string) (expl string) {

var e int

if file, err := os.OpenFile(f, os.O_RDWR|os.O_CREATE, 0666); err == nil {

if _, err := file.WriteString(s); err == nil {

e = 0

} else {

e = 1

}

} else {

e = 99

}

return explainError(e) + f

}

// explainError takes the file name and the error index

// and returns an explicit error text

func explainError(e int) (s string) {

switch e {

case 0:

s = "Successful write to file: "

case 1:

s = "There was an error writing to file: "

case 99:

s = "You got the file name (and/or its path) wrong: "

}

return s

}
Post by k***@public.gmane.org
package main
import (
"bufio"
"os"
)
func main() {
file, _ := os.OpenFile("/nowhere/", os.O_WRONLY|os.O_CREATE, 0666)
writer := bufio.NewWriter(file);
writer.WriteString("foobar\n")
}
Run this, and what will you get? Nothing. No error, no stacktrace ...
absolutely nothing. Nada.
I know that programers should check the error codes and should be super
smart, and should have tests for their code, and should not have deadlines,
and should be handsome ... but in reality, well you have been there.
This applies to any error handling mechanism error codes, exceptions or
you name it... as someone mentioned Go (or any language) will not do the
error checking, the programmer will.
So when the programmer, god forbid, fails to do his job I would rather
have a180 line stacktrace pinpointing me where the stupid programmer messed
up.
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
Steven Rice
2012-09-27 13:20:51 UTC
Permalink
So you want exceptions to arise? It sounds like you want to work with bad
programmers. The only reasons exceptions exist is to force someone to
handle an error, if you really need an exception to remind you to think
about what can go wrong in your code, to remind you to check
and sanitize your input, to remind you to program, then you are not a very
good programmer. Don't work with APIs that ignore errors, don't write APIs
that ignore errors. If you do that then you'll never have to worry about
them. If you work in a team of potentially bad programmers, here's an idea:
write each others test cases as well as your own. Think of input that they
may not expect (like your non existent file name) and see if it passes.
Post by k***@public.gmane.org
package main
import (
"bufio"
"os"
)
func main() {
file, _ := os.OpenFile("/nowhere/", os.O_WRONLY|os.O_CREATE, 0666)
writer := bufio.NewWriter(file);
writer.WriteString("foobar\n")
}
Run this, and what will you get? Nothing. No error, no stacktrace ...
absolutely nothing. Nada.
I know that programers should check the error codes and should be super
smart, and should have tests for their code, and should not have deadlines,
and should be handsome ... but in reality, well you have been there.
This applies to any error handling mechanism error codes, exceptions or
you name it... as someone mentioned Go (or any language) will not do the
error checking, the programmer will.
So when the programmer, god forbid, fails to do his job I would rather
have a180 line stacktrace pinpointing me where the stupid programmer messed
up.
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
Harley Laue
2012-09-27 16:43:34 UTC
Permalink
In addition to the "letting someone else deal with it" mentality of
exceptions, it's also done at runtime. So poorly tested code and code
paths that aren't taken frequently are more likely to crash your
program. Whereas the provided example, the programmer actively and
knowingly ignored the error. So this is a particularly bad example
(and as other have pointed out, it's actually less verbose to ignore
the error in Go than it is in exception based languages :P)

I think I'm done watching this thread. There's nothing anyone can say
to show the knotwelkum that he is misguided at best (or IMO wrong) in
his opinions of how errors should be handled (in his case, not
handling them until it blows up.) With everything that's already been
said, I think he must be content writing buggy/untested code. I guess
that's just his prerogative.
Post by Steven Rice
So you want exceptions to arise? It sounds like you want to work with bad
programmers. The only reasons exceptions exist is to force someone to handle
an error, if you really need an exception to remind you to think about what
can go wrong in your code, to remind you to check and sanitize your input,
to remind you to program, then you are not a very good programmer. Don't
work with APIs that ignore errors, don't write APIs that ignore errors. If
you do that then you'll never have to worry about them. If you work in a
team of potentially bad programmers, here's an idea: write each others test
cases as well as your own. Think of input that they may not expect (like
your non existent file name) and see if it passes.
Post by k***@public.gmane.org
package main
import (
"bufio"
"os"
)
func main() {
file, _ := os.OpenFile("/nowhere/", os.O_WRONLY|os.O_CREATE, 0666)
writer := bufio.NewWriter(file);
writer.WriteString("foobar\n")
}
Run this, and what will you get? Nothing. No error, no stacktrace ...
absolutely nothing. Nada.
I know that programers should check the error codes and should be super
smart, and should have tests for their code, and should not have deadlines,
and should be handsome ... but in reality, well you have been there.
This applies to any error handling mechanism error codes, exceptions or
you name it... as someone mentioned Go (or any language) will not do the
error checking, the programmer will.
So when the programmer, god forbid, fails to do his job I would rather
have a180 line stacktrace pinpointing me where the stupid programmer messed
up.
Post by k***@public.gmane.org
Its a shame that such a fantastic language is missing a better way to
deal with errors.
Exceptions might not be perfect, but are damn better than checking each
and every function call.
Or am I missing something?
I just read a pair of posts that expresses these ideas much better than
what I could here.
http://uberpython.wordpress.com/2012/09/23/why-im-not-leaving-python-for-go/
http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html
As one of the comments I read said: 99% of the time I need to code the
happy path and if something breaks in the middle the error handling is
exactly the same: log the error, close resources, send the caller an error
code or message, end of the story. I don't want to check every freaking
single function invocation for errors.
Its a shame, I really wanted to use go.
--
--
David Leimbach
2012-09-27 20:52:05 UTC
Permalink
<cutting a lot, sorry. Trying to get to the meat of your point, I think>

So when the programmer, god forbid, fails to do his job I would rather have
Post by k***@public.gmane.org
a180 line stacktrace pinpointing me where the stupid programmer messed up.
If Go provided stack traces for errors that were != nil, and not captured
in a variable would you think Go's error handling was better?

My thinking is something like

x, _ := f();

is an explicit ignoring of the error from f(), and that if an error occurs,
nothing new should happen.

However for calls like

fmt.Printf("blah")

This is not explicitly ignoring the error, and one could say the lazy
programmer should be told about such a failure. If you really don't care
you must write

_,_ = fmt.Printf("blah")

or

numBytes, _ := fmt.Printf("blah")

instead.

This is a lot better than having exceptions creep up the call stack to be
ultimately squelched by a

catch (Exception e) {}

The error type is literally part of the language so I suspect someone could
one day do something about this, if it made sense to do so.

It could be pretty ugly to implement, but I've never tried to do such a
thing, so perhaps not?

I still feel very strongly that errors should not propagate up the stack
unless explicitly wired to do so via a chain of error returns, because
implicit behaviors are dangerous in general and have been a source of bugs
in languages like C++ for years (like 'explicit' keywords for single
argument constructors).

Being explicit really helps with readability and maintenance of code bases.
Writing the code is only part of the story of a software life cycle.


--
k***@public.gmane.org
2012-09-27 21:04:02 UTC
Permalink
Not really. The problem with your "suggestion" is that it would be caught
at compile time (which is good) but the lazy programmer will still just do
_,_ := x() just to get past it.
The real problem is at runtime, where you would be completely lost as to
where the problem is.
Of course the same goes for exceptions. The lazy programmer could simply
catch and ignore the exception...(that is also why I favor unchecked
exceptions... but that is another matter).

Thanks to all for your answers.
Post by David Leimbach
<cutting a lot, sorry. Trying to get to the meat of your point, I think>
So when the programmer, god forbid, fails to do his job I would rather
Post by k***@public.gmane.org
have a180 line stacktrace pinpointing me where the stupid programmer messed
up.
If Go provided stack traces for errors that were != nil, and not captured
in a variable would you think Go's error handling was better?
My thinking is something like
x, _ := f();
is an explicit ignoring of the error from f(), and that if an error
occurs, nothing new should happen.
However for calls like
fmt.Printf("blah")
This is not explicitly ignoring the error, and one could say the lazy
programmer should be told about such a failure. If you really don't care
you must write
_,_ = fmt.Printf("blah")
or
numBytes, _ := fmt.Printf("blah")
instead.
This is a lot better than having exceptions creep up the call stack to be
ultimately squelched by a
catch (Exception e) {}
The error type is literally part of the language so I suspect someone
could one day do something about this, if it made sense to do so.
It could be pretty ugly to implement, but I've never tried to do such a
thing, so perhaps not?
I still feel very strongly that errors should not propagate up the stack
unless explicitly wired to do so via a chain of error returns, because
implicit behaviors are dangerous in general and have been a source of bugs
in languages like C++ for years (like 'explicit' keywords for single
argument constructors).
Being explicit really helps with readability and maintenance of code
bases. Writing the code is only part of the story of a software life cycle.
--
Patrick Mylund Nielsen
2012-09-27 21:21:45 UTC
Permalink
but the *bad* programmer will still just do _,_ := x() just to get past
it.

FTFY

In languages with exceptions, ignoring errors is implicit and excusable. In
Go, it is explicit and inexcusable. That leads to better code on average.
Only code written by bad programmers will be riddled with "foo, _ :=
somethingThatMightFail()".
Not really. The problem with your "suggestion" is that it would be caught
at compile time (which is good) but the lazy programmer will still just do
_,_ := x() just to get past it.
The real problem is at runtime, where you would be completely lost as to
where the problem is.
Of course the same goes for exceptions. The lazy programmer could simply
catch and ignore the exception...(that is also why I favor unchecked
exceptions... but that is another matter).
Thanks to all for your answers.
Post by David Leimbach
<cutting a lot, sorry. Trying to get to the meat of your point, I think>
So when the programmer, god forbid, fails to do his job I would rather
Post by k***@public.gmane.org
have a180 line stacktrace pinpointing me where the stupid programmer messed
up.
If Go provided stack traces for errors that were != nil, and not captured
in a variable would you think Go's error handling was better?
My thinking is something like
x, _ := f();
is an explicit ignoring of the error from f(), and that if an error
occurs, nothing new should happen.
However for calls like
fmt.Printf("blah")
This is not explicitly ignoring the error, and one could say the lazy
programmer should be told about such a failure. If you really don't care
you must write
_,_ = fmt.Printf("blah")
or
numBytes, _ := fmt.Printf("blah")
instead.
This is a lot better than having exceptions creep up the call stack to be
ultimately squelched by a
catch (Exception e) {}
The error type is literally part of the language so I suspect someone
could one day do something about this, if it made sense to do so.
It could be pretty ugly to implement, but I've never tried to do such a
thing, so perhaps not?
I still feel very strongly that errors should not propagate up the stack
unless explicitly wired to do so via a chain of error returns, because
implicit behaviors are dangerous in general and have been a source of bugs
in languages like C++ for years (like 'explicit' keywords for single
argument constructors).
Being explicit really helps with readability and maintenance of code
bases. Writing the code is only part of the story of a software life cycle.
--
--
Kevin Gillette
2012-09-27 21:33:51 UTC
Permalink
I very often see, `_, err := something()`, but I've yet to see an
experienced go programmer do `x, _ := something()`. What that tells me is
the error is the last thing that a normal go programmer will ignore.

On Thursday, September 27, 2012 3:21:52 PM UTC-6, Patrick Mylund Nielsen
Post by Patrick Mylund Nielsen
but the *bad* programmer will still just do _,_ := x() just to get past
it.
FTFY
In languages with exceptions, ignoring errors is implicit and excusable.
In Go, it is explicit and inexcusable. That leads to better code on
average. Only code written by bad programmers will be riddled with "foo, _
:= somethingThatMightFail()".
Not really. The problem with your "suggestion" is that it would be caught
at compile time (which is good) but the lazy programmer will still just do
_,_ := x() just to get past it.
The real problem is at runtime, where you would be completely lost as to
where the problem is.
Of course the same goes for exceptions. The lazy programmer could simply
catch and ignore the exception...(that is also why I favor unchecked
exceptions... but that is another matter).
Thanks to all for your answers.
Post by David Leimbach
<cutting a lot, sorry. Trying to get to the meat of your point, I think>
So when the programmer, god forbid, fails to do his job I would rather
Post by k***@public.gmane.org
have a180 line stacktrace pinpointing me where the stupid programmer messed
up.
If Go provided stack traces for errors that were != nil, and not
captured in a variable would you think Go's error handling was better?
My thinking is something like
x, _ := f();
is an explicit ignoring of the error from f(), and that if an error
occurs, nothing new should happen.
However for calls like
fmt.Printf("blah")
This is not explicitly ignoring the error, and one could say the lazy
programmer should be told about such a failure. If you really don't care
you must write
_,_ = fmt.Printf("blah")
or
numBytes, _ := fmt.Printf("blah")
instead.
This is a lot better than having exceptions creep up the call stack to
be ultimately squelched by a
catch (Exception e) {}
The error type is literally part of the language so I suspect someone
could one day do something about this, if it made sense to do so.
It could be pretty ugly to implement, but I've never tried to do such a
thing, so perhaps not?
I still feel very strongly that errors should not propagate up the stack
unless explicitly wired to do so via a chain of error returns, because
implicit behaviors are dangerous in general and have been a source of bugs
in languages like C++ for years (like 'explicit' keywords for single
argument constructors).
Being explicit really helps with readability and maintenance of code
bases. Writing the code is only part of the story of a software life cycle.
--
--
andrey mirtchovski
2012-09-27 21:36:48 UTC
Permalink
Post by Kevin Gillette
the error is the last thing that a normal go programmer will ignore.
but go-nuts threads about Go Errors are the first things normal go
programmers will ignore ;)

--
David Leimbach
2012-09-27 23:28:52 UTC
Permalink
Post by Kevin Gillette
I very often see, `_, err := something()`, but I've yet to see an
experienced go programmer do `x, _ := something()`. What that tells me is
the error is the last thing that a normal go programmer will ignore.
So maybe I was on to something with my proposal? (Or perhaps just "on
something")

_,_ = something()

in the case where you're really sure you want to explicitly ignore the
error. This is really uncommon, and should stick out like a sore thumb.

_,err := something()

when you really want to only handle the error. this seems idiomatic to go.

and get a stack trace from the run time for ignoring the error when you do

something()

without ever even capturing the possibility of an error happening, but only
when the error really happens! People would choose this approach when
they're doing something innocuous which may usually never fail, but when it
does you just expect things to crash anyway.
Post by Kevin Gillette
On Thursday, September 27, 2012 3:21:52 PM UTC-6, Patrick Mylund Nielsen
Post by k***@public.gmane.org
but the *bad* programmer will still just do _,_ := x() just to get
past it.
FTFY
In languages with exceptions, ignoring errors is implicit and excusable.
In Go, it is explicit and inexcusable. That leads to better code on
average. Only code written by bad programmers will be riddled with "foo, _
:= somethingThatMightFail()".
Not really. The problem with your "suggestion" is that it would be
caught at compile time (which is good) but the lazy programmer will still
just do _,_ := x() just to get past it.
The real problem is at runtime, where you would be completely lost as to
where the problem is.
Of course the same goes for exceptions. The lazy programmer could
simply catch and ignore the exception...(that is also why I favor unchecked
exceptions... but that is another matter).
Thanks to all for your answers.
Post by David Leimbach
<cutting a lot, sorry. Trying to get to the meat of your point, I think>
So when the programmer, god forbid, fails to do his job I would rather
Post by k***@public.gmane.org
have a180 line stacktrace pinpointing me where the stupid programmer messed
up.
If Go provided stack traces for errors that were != nil, and not
captured in a variable would you think Go's error handling was better?
My thinking is something like
x, _ := f();
is an explicit ignoring of the error from f(), and that if an error
occurs, nothing new should happen.
However for calls like
fmt.Printf("blah")
This is not explicitly ignoring the error, and one could say the lazy
programmer should be told about such a failure. If you really don't care
you must write
_,_ = fmt.Printf("blah")
or
numBytes, _ := fmt.Printf("blah")
instead.
This is a lot better than having exceptions creep up the call stack to
be ultimately squelched by a
catch (Exception e) {}
The error type is literally part of the language so I suspect someone
could one day do something about this, if it made sense to do so.
It could be pretty ugly to implement, but I've never tried to do such a
thing, so perhaps not?
I still feel very strongly that errors should not propagate up the
stack unless explicitly wired to do so via a chain of error returns,
because implicit behaviors are dangerous in general and have been a source
of bugs in languages like C++ for years (like 'explicit' keywords for
single argument constructors).
Being explicit really helps with readability and maintenance of code
bases. Writing the code is only part of the story of a software life cycle.
--
--
Dave Cheney
2012-09-27 23:53:38 UTC
Permalink
Received: by 10.50.12.169 with SMTP id z9mr46999igb.1.1348790022001;
Thu, 27 Sep 2012 16:53:42 -0700 (PDT)
X-BeenThere: golang-nuts-/***@public.gmane.org
Received: by 10.42.249.136 with SMTP id mk8ls893107icb.9.gmail; Thu, 27 Sep
2012 16:53:39 -0700 (PDT)
Received: by 10.43.105.135 with SMTP id dq7mr2900296icc.3.1348790019111;
Thu, 27 Sep 2012 16:53:39 -0700 (PDT)
Received: by 10.43.105.135 with SMTP id dq7mr2900295icc.3.1348790019102;
Thu, 27 Sep 2012 16:53:39 -0700 (PDT)
Received: from mail-oa0-f45.google.com (mail-oa0-f45.google.com [209.85.219.45])
by gmr-mx.google.com with ESMTPS id s9si9377igw.0.2012.09.27.16.53.38
(version=TLSv1/SSLv3 cipher=OTHER);
Thu, 27 Sep 2012 16:53:38 -0700 (PDT)
Received-SPF: neutral (google.com: 209.85.219.45 is neither permitted nor denied by best guess record for domain of dave-7L4Cwp9BzA+sTnJN9+***@public.gmane.org) client-ip=209.85.219.45;
Received: by mail-oa0-f45.google.com with SMTP id i18so3205202oag.32
for <golang-nuts-/***@public.gmane.org>; Thu, 27 Sep 2012 16:53:38 -0700 (PDT)
Received: by 10.182.179.104 with SMTP id df8mr4448407obc.90.1348790018653;
Thu, 27 Sep 2012 16:53:38 -0700 (PDT)
Received: by 10.76.69.69 with HTTP; Thu, 27 Sep 2012 16:53:38 -0700 (PDT)
In-Reply-To: <a4b6a6ae-2ed5-4c30-985b-7624c70314ac-/***@public.gmane.org>
X-Gm-Message-State: ALoCoQn3PBNtEFOfgRMSOeN8sSsWPwLhxjImEeiBGlAgS7lJU7rLUn164NLbjFXL/ClYhrIoT2zZ
X-Original-Sender: dave-7L4Cwp9BzA+sTnJN9+***@public.gmane.org
X-Original-Authentication-Results: gmr-mx.google.com; spf=neutral (google.com:
209.85.219.45 is neither permitted nor denied by best guess record for domain
of dave-7L4Cwp9BzA+sTnJN9+***@public.gmane.org) smtp.mail=dave-7L4Cwp9BzA+sTnJN9+***@public.gmane.org
Precedence: list
Mailing-list: list golang-nuts-/***@public.gmane.org; contact golang-nuts+owners-/***@public.gmane.org
List-ID: <golang-nuts.googlegroups.com>
X-Google-Group-Id: 332403668183
List-Post: <http://groups.google.com/group/golang-nuts/post?hl=en-US>, <mailto:golang-nuts-/***@public.gmane.org>
List-Help: <http://groups.google.com/support/?hl=en-US>, <mailto:golang-nuts+help-/***@public.gmane.org>
List-Archive: <http://groups.google.com/group/golang-nuts?hl=en-US>
Sender: golang-nuts-/***@public.gmane.org
List-Subscribe: <http://groups.google.com/group/golang-nuts/subscribe?hl=en-US>,
<mailto:golang-nuts+subscribe-/***@public.gmane.org>
List-Unsubscribe: <http://groups.google.com/group/golang-nuts/subscribe?hl=en-US>,
<mailto:googlegroups-manage+332403668183+unsubscribe-/***@public.gmane.org>
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.go.general/72728>
Post by David Leimbach
and get a stack trace from the run time for ignoring the error when you do
something()
without ever even capturing the possibility of an error happening, but only
when the error really happens! People would choose this approach when
they're doing something innocuous which may usually never fail, but when it
does you just expect things to crash anyway.
So, to clarify, your proposal is

fmt.Println("Hello world")

should panic if any return value of type error from this function, is
not assigned to a variable (or the _ variable), and that value would
be non nil ?

Cheers

Dave

--
Michael Jones
2012-09-27 23:58:47 UTC
Permalink
Interesting! Some points to consider:

+ Ignoring function return values, or one or more of the final ones, is a
capability of the language.

+ Some functions use a return value, often the final one, to signal an
error.

+ Some call sites of functions that return a final error argument ignore
it.

There are varying opinions on how best to deal with error returns (always
check, never check, sometimes check and hope for the best, etc.) and also
on what should happen when a returned error is ignored. What does not seem
to be mentioned is that the *language* does not know about errors. There is
a package "errors" and the standard library uses it, so you could say that
there is a convention about error handling, but I don't think we can say
that the compiler is aware of anything special. (Am I wrong?)

Given this state of affairs, I'm not sure what magic enforcement a compiler
can do for unexamined final return values that happen to have special
meaning to a package.

Of course, there is still the option of making an error something that the
language understands and thus can enforce in various ways.
Post by David Leimbach
Post by Kevin Gillette
I very often see, `_, err := something()`, but I've yet to see an
experienced go programmer do `x, _ := something()`. What that tells me is
the error is the last thing that a normal go programmer will ignore.
So maybe I was on to something with my proposal? (Or perhaps just "on
something")
_,_ = something()
in the case where you're really sure you want to explicitly ignore the
error. This is really uncommon, and should stick out like a sore thumb.
_,err := something()
when you really want to only handle the error. this seems idiomatic to go.
and get a stack trace from the run time for ignoring the error when you do
something()
without ever even capturing the possibility of an error happening, but
only when the error really happens! People would choose this approach
when they're doing something innocuous which may usually never fail, but
when it does you just expect things to crash anyway.
Post by Kevin Gillette
On Thursday, September 27, 2012 3:21:52 PM UTC-6, Patrick Mylund Nielsen
Post by k***@public.gmane.org
but the *bad* programmer will still just do _,_ := x() just to get
past it.
FTFY
In languages with exceptions, ignoring errors is implicit and excusable.
In Go, it is explicit and inexcusable. That leads to better code on
average. Only code written by bad programmers will be riddled with "foo, _
:= somethingThatMightFail()".
Not really. The problem with your "suggestion" is that it would be
caught at compile time (which is good) but the lazy programmer will still
just do _,_ := x() just to get past it.
The real problem is at runtime, where you would be completely lost as
to where the problem is.
Of course the same goes for exceptions. The lazy programmer could
simply catch and ignore the exception...(that is also why I favor unchecked
exceptions... but that is another matter).
Thanks to all for your answers.
Post by David Leimbach
<cutting a lot, sorry. Trying to get to the meat of your point, I think>
So when the programmer, god forbid, fails to do his job I would rather
Post by k***@public.gmane.org
have a180 line stacktrace pinpointing me where the stupid programmer messed
up.
If Go provided stack traces for errors that were != nil, and not
captured in a variable would you think Go's error handling was better?
My thinking is something like
x, _ := f();
is an explicit ignoring of the error from f(), and that if an error
occurs, nothing new should happen.
However for calls like
fmt.Printf("blah")
This is not explicitly ignoring the error, and one could say the lazy
programmer should be told about such a failure. If you really don't care
you must write
_,_ = fmt.Printf("blah")
or
numBytes, _ := fmt.Printf("blah")
instead.
This is a lot better than having exceptions creep up the call stack to
be ultimately squelched by a
catch (Exception e) {}
The error type is literally part of the language so I suspect someone
could one day do something about this, if it made sense to do so.
It could be pretty ugly to implement, but I've never tried to do such
a thing, so perhaps not?
I still feel very strongly that errors should not propagate up the
stack unless explicitly wired to do so via a chain of error returns,
because implicit behaviors are dangerous in general and have been a source
of bugs in languages like C++ for years (like 'explicit' keywords for
single argument constructors).
Being explicit really helps with readability and maintenance of code
bases. Writing the code is only part of the story of a software life cycle.
--
--
--
Michael T. Jones | Chief Technology Advocate | mtj-hpIqsD4AKlfQT0dZR+***@public.gmane.org | +1
650-335-5765

--
Ian Lance Taylor
2012-09-28 00:34:20 UTC
Permalink
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=google.com; s=20120113;
h=x-beenthere:received-spf:mime-version:in-reply-to:references:date
:message-id:subject:from:to:cc:x-system-of-record:x-gm-message-state
:x-original-sender:x-original-authentication-results:precedence
:mailing-list:list-id:x-google-group-id:list-post:list-help
:list-archive:sender:list-subscribe:list-unsubscribe:content-type;
bh=8Ce8evhd9FXUS9eyrC4BIx+z/camcIoe8BKB43I8eS4=;
b=B4eks+m5tZuDZYV5uWiu3Tl1McNOLzkzg1jSVklGj53UxvkqD0j3dUx7tZ0phB3x5z
jXLK5O9luO9d3ZZ/e5CUYrXRR2kVCb3l8y9X9Y6lmciGvxDVQYD9F+HDXmcY8ECuppQW
JD3NPmO/++8fd9NHRy3NiNFDHjU1LwMp1ZacOybQHwnKRrqBFWlLJfPSqa04bhhr5acH
yYtoxAVxxqe5leUhETkUo1u6Ewfw2ZVN5QleUEOJWKLxn5l2Ot4llZ6t1xBOE7PQ+mtO
xFInSwQongoj+TV7IvhQ4vOKmA63OOMvk0h9iANMFD5PcxNWJbIrF8
Received: by 10.68.189.74 with SMTP id gg10mr1862127pbc.5.1348792462971;
Thu, 27 Sep 2012 17:34:22 -0700 (PDT)
X-BeenThere: golang-nuts-/***@public.gmane.org
Received: by 10.68.237.161 with SMTP id vd1ls12052739pbc.3.gmail; Thu, 27 Sep
2012 17:34:20 -0700 (PDT)
Received: by 10.66.75.39 with SMTP id z7mr1841164pav.26.1348792460665;
Thu, 27 Sep 2012 17:34:20 -0700 (PDT)
Received: by 10.66.75.39 with SMTP id z7mr1841163pav.26.1348792460657;
Thu, 27 Sep 2012 17:34:20 -0700 (PDT)
Received: from mail-pb0-f50.google.com (mail-pb0-f50.google.com [209.85.160.50])
by gmr-mx.google.com with ESMTPS id p7si1969636pby.0.2012.09.27.17.34.20
(version=TLSv1/SSLv3 cipher=OTHER);
Thu, 27 Sep 2012 17:34:20 -0700 (PDT)
Received-SPF: pass (google.com: domain of iant-hpIqsD4AKlfQT0dZR+***@public.gmane.org designates 209.85.160.50 as permitted sender) client-ip=209.85.160.50;
Received: by pbcmd4 with SMTP id md4so1670183pbc.9
for <golang-nuts-/***@public.gmane.org>; Thu, 27 Sep 2012 17:34:20 -0700 (PDT)
Received: by 10.66.87.66 with SMTP id v2mr13247575paz.71.1348792460567;
Thu, 27 Sep 2012 17:34:20 -0700 (PDT)
Received: by 10.66.87.66 with SMTP id v2mr13247552paz.71.1348792460370; Thu,
27 Sep 2012 17:34:20 -0700 (PDT)
Received: by 10.68.129.170 with HTTP; Thu, 27 Sep 2012 17:34:20 -0700 (PDT)
In-Reply-To: <CAB3Vzbp_hdbBAxSC_+bn9oP=coP-WFuZJ4LxXc4-7TJGH0a1Hw-JsoAwUIsXosN+***@public.gmane.org>
X-System-Of-Record: true
X-Gm-Message-State: ALoCoQn69z5Ej839nX90tAYiy4UjYynkxzzu4NavsD74dyBYS6USevjtHyY0Ql0RBk8jkwPSvKMQLYyY0ZLGNNQWqvE6dHoXCB41ZuOuD388yrEeqknbeK7ffopr3E/O0lo4vMsizMMWqiDsvRuprC763ei1lYZySbXXwIfz5j+PrtJARVqJ6p0IPseJCSpYdiurOC72C2IOnvgpY9BXU5phmcJ0FxIjmw==
X-Original-Sender: iant-hpIqsD4AKlfQT0dZR+***@public.gmane.org
X-Original-Authentication-Results: gmr-mx.google.com; spf=pass (google.com:
domain of iant-hpIqsD4AKlfQT0dZR+***@public.gmane.org designates 209.85.160.50 as permitted sender)
smtp.mail=iant-hpIqsD4AKlfQT0dZR+***@public.gmane.org; dkim=pass header.i=@google.com
Precedence: list
Mailing-list: list golang-nuts-/***@public.gmane.org; contact golang-nuts+owners-/***@public.gmane.org
List-ID: <golang-nuts.googlegroups.com>
X-Google-Group-Id: 332403668183
List-Post: <http://groups.google.com/group/golang-nuts/post?hl=en-US>, <mailto:golang-nuts-/***@public.gmane.org>
List-Help: <http://groups.google.com/support/?hl=en-US>, <mailto:golang-nuts+help-/***@public.gmane.org>
List-Archive: <http://groups.google.com/group/golang-nuts?hl=en-US>
Sender: golang-nuts-/***@public.gmane.org
List-Subscribe: <http://groups.google.com/group/golang-nuts/subscribe?hl=en-US>,
<mailto:golang-nuts+subscribe-/***@public.gmane.org>
List-Unsubscribe: <http://groups.google.com/group/golang-nuts/subscribe?hl=en-US>,
<mailto:googlegroups-manage+332403668183+unsubscribe-/***@public.gmane.org>
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.go.general/72730>
Post by Michael Jones
There are varying opinions on how best to deal with error returns (always
check, never check, sometimes check and hope for the best, etc.) and also on
what should happen when a returned error is ignored. What does not seem to
be mentioned is that the *language* does not know about errors. There is a
package "errors" and the standard library uses it, so you could say that
there is a convention about error handling, but I don't think we can say
that the compiler is aware of anything special. (Am I wrong?)
The name "error" is a predeclared identifier in the language, like
"int" and so on. So while the language doesn't currently give that
type any special semantics, and I'm not at all sure that it should, it
is at least within the realm of possibility.

Ian

--
Michael Jones
2012-09-28 00:52:07 UTC
Permalink
...which leaves open a long list of options, like:

func (name *type) example(arg int) (int, float64, error) { }

and

a, b := example(1)

where the compiler knows that there is an error returned and that it has
special powers, as in the above where the implication could be there is an
unchecked error here, so I will:

1. refuse to compile

2. print a stack trace when error is non-nill. ;-)

3. only compile if the function making the call ALSO has an error return
and when error comes back non-nill, automatically return from the function
and pass that error as the function's error value. (implicit assignment of
invisible return value and invisible "if not ok return error") in such
cases. Rob might puke all over this, but it is one of the possibles. Think
of this as a soft exception. It only means that errors are always unpacked
from the return and examined, making ",ok" universal even when uncoded by
the developer.

4. similar to #3 but instead of returning, look for an error switch in
scope and use that if it exists.

:
many others ideas, no doubt
Post by k***@public.gmane.org
Post by Michael Jones
There are varying opinions on how best to deal with error returns (always
check, never check, sometimes check and hope for the best, etc.) and
also on
Post by Michael Jones
what should happen when a returned error is ignored. What does not seem
to
Post by Michael Jones
be mentioned is that the *language* does not know about errors. There is
a
Post by Michael Jones
package "errors" and the standard library uses it, so you could say that
there is a convention about error handling, but I don't think we can say
that the compiler is aware of anything special. (Am I wrong?)
The name "error" is a predeclared identifier in the language, like
"int" and so on. So while the language doesn't currently give that
type any special semantics, and I'm not at all sure that it should, it
is at least within the realm of possibility.
Ian
--
Michael T. Jones | Chief Technology Advocate | mtj-hpIqsD4AKlfQT0dZR+***@public.gmane.org | +1
650-335-5765

--
David Leimbach
2012-09-28 00:55:12 UTC
Permalink
Yeah. Errors are special in the language to a degree and I don't know that I'm advocating any changes yet; simply sugesting that one can potentially provide different default behavior for error since it is already special.

Also I'm saying that behavior can be explicitly overridden in a way that you could read and identify fairly quickly reusing the token that currently means "ignore" for that purpose.

It almost feels consistent enough to be reasonable. I question the overall value of it though.

I wonder how it would impact the existing corpus of go 1.0+ code.

--
si guy
2012-09-28 02:48:12 UTC
Permalink
Are you suggesting a function definition flag that says "mr. Compiler, please error if my return values are ignored."?
Something like if func is capitalized?

--

David Leimbach
2012-09-28 00:55:45 UTC
Permalink
Yeah. Errors are special in the language to a degree and I don't know that I'm advocating any changes yet; simply sugesting that one can potentially provide different default behavior for error since it is already special.

Also I'm saying that behavior can be explicitly overridden in a way that you could read and identify fairly quickly reusing the token that currently means "ignore" for that purpose.

It almost feels consistent enough to be reasonable. I question the overall value of it though.

I wonder how it would impact the existing corpus of go 1.0+ code.

--
David Leimbach
2012-09-27 23:21:03 UTC
Permalink
Post by k***@public.gmane.org
Not really. The problem with your "suggestion" is that it would be caught
at compile time (which is good) but the lazy programmer will still just do
_,_ := x() just to get past it.
Lazy programmers are ok. It's the crappy ones you can't do anything about.

Also I was not suggesting something that would get caught at compile time.
Please re-read my post. My point was that since errors are a built-in
type in the Go language, the compiler can leave behind code to emit a stack
trace like thing when something "non-nil" happens where an otherwise
not-explicitly ignored error would go. I'll admit this seems pretty heavy
handed, and possibly is quite stupid to do, but it might address some
people's criticisms and might be worth a real discussion.

That would make it so that the programmer who's ignoring errors on purpose
could write something really explicit like "_,_ = blah()" to say "I really
don't care about this error". But folks who write just "blah()", will get
a stack trace if something occurs, because they didn't explicitly ask for
the error to be ignored.

I've seen no examples of languages that address the "bad programmer
problem". What I think can be done is make it very explicit in code where
people are doing "bad things".

I don't think we can stop people from doing bad things in a language. Even
Haskell has unsafePerformIO, which can turn something like ``myprint
"hello" '' into something that means "fire all the missles!"
Post by k***@public.gmane.org
The real problem is at runtime, where you would be completely lost as to
where the problem is.
Of course the same goes for exceptions. The lazy programmer could simply
catch and ignore the exception...(that is also why I favor unchecked
exceptions... but that is another matter).
You can easily catch and ignore unchecked exceptions.

In C++ it's as simple as

catch(...) {}

In Java you can catch Throwable, which can even catch OutOfMemoryError.

Thanks to all for your answers.
Post by k***@public.gmane.org
<cutting a lot, sorry. Trying to get to the meat of your point, I think>
So when the programmer, god forbid, fails to do his job I would rather
Post by k***@public.gmane.org
have a180 line stacktrace pinpointing me where the stupid programmer messed
up.
If Go provided stack traces for errors that were != nil, and not captured
in a variable would you think Go's error handling was better?
My thinking is something like
x, _ := f();
is an explicit ignoring of the error from f(), and that if an error
occurs, nothing new should happen.
However for calls like
fmt.Printf("blah")
This is not explicitly ignoring the error, and one could say the lazy
programmer should be told about such a failure. If you really don't care
you must write
_,_ = fmt.Printf("blah")
or
numBytes, _ := fmt.Printf("blah")
instead.
This is a lot better than having exceptions creep up the call stack to be
ultimately squelched by a
catch (Exception e) {}
The error type is literally part of the language so I suspect someone
could one day do something about this, if it made sense to do so.
It could be pretty ugly to implement, but I've never tried to do such a
thing, so perhaps not?
I still feel very strongly that errors should not propagate up the stack
unless explicitly wired to do so via a chain of error returns, because
implicit behaviors are dangerous in general and have been a source of bugs
in languages like C++ for years (like 'explicit' keywords for single
argument constructors).
Being explicit really helps with readability and maintenance of code
bases. Writing the code is only part of the story of a software life cycle.
--
Loading...