See, e.g. here
<https://groups.google.com/d/topic/golang-nuts/ROr5jveMQvg/discussion> or
here <https://groups.google.com/d/topic/golang-nuts/68J-mLCC1JI/discussion> for
previous discussions of very similar (even mostly identical) proposals.

What I always dislike about these kinds of proposals is, that they are
encouraging not handling errors, but instead just passing them up-stack. In
general, all of the sites where you are checking for errors will signify
different error conditions, that should be communicated differently
upstream. For example:

db.Prepare("INSERT INTO userinfo(username, departname, created)
values(?,?,?)")
-> This could fail for basically two reasons: Either communication with
your database somehow failed (e.g. a broken network connection), in which
case you want to return the equivalent of an HTTP 503 error, or the syntax
of your statement is wrong, in which case I'd argue panic'ing would be the
correct thing - at the very least, returning the equivalent of a 500.

stmt.Exec("astaxie", "研发部门", "2012-12-09")
-> Either a 503. Or 400, 403, 409…

res.LastInsertId()
-> 500 or 501?

The issue is, that by simply checking for nil and passing it along, you are
*not handling your error*. Different error conditions require different
error handling and what the correct error handling is, depends heavily on
the application. An ENODIR error in one line of code can signify a totally
different error condition than the same error two lines later. So all of
these proposals are born out of an exception-style idea of how error
handling is supposed to work; deep within the call stack something goes
wrong and that something is then just bubbled up to be someone else's
problem. Good error handling just can't be well abbreviated in this way -
at least not generically. It's too application-specific for that.

On Mon, Sep 4, 2017 at 8:27 PM, <martin.r...@programmfabrik.de> wrote:

> Seriously? And yes, I have read https://blog.golang.org/errors-are-values.
> ..
>
> The best case reduction I found is:
>
> ...
> res, err = stmt.Exec("astaxieupdate", id)
> checkError(err)
> ...
>
> Still, I need this after each line of calling a function which may return
> an error.
>

A better take-away from that blog post would have been, to orient yourself
around the example of a writer given. You could, for example, provide a
one-time abstraction that wraps *sql.DB and collects the error. I'd agree
that the sql package tends to not be amazing for that, because of its set
of interdependent types, it is still possible. For example, with this
<https://play.golang.org/p/kdgBUqWeR->, you could write

d := &errDB{db: d}
stmt := d.Prepare("INSERT INTO…")
res := stmt.Exec(…)
id := res.LastInsertId()
stmt := d.Prepare("UPDATE…")
res := stmt.Exec(…, id)
affect := res.RowsAffected()
return d.err

Now… this isn't really nice either (see above. sql isn't really
well-designed for this. You'd probably try and implement a driver for this,
but sql doesn't make that easy either). And it's a bad idea for all the
same reasons the watch-proposal isn't a great idea here. But it illustrates
a far more effective take-away from that blog post.


>
> I bet this is not pleasant to do in larger code bases and it also takes
> away focus from what is actually happening.
>
> 50-80% of all lines of code in my example deal with error handling?
>
> This is not good. Seriously.
>
> And don't get me wrong, there is a lot of things I really like, love and
> adore about Go, but catching errors needs an improved syntax!
>
> And I am not proposing try...catch here.
>
> How about introducing a new piece of syntax
>
> "watch if  .... "
>
> which tells the compiler to watch out for changes in a given SimpleStmt
>
> The same code as above would look like this:
>
> var err Error
>
> watch if err != nil {
>   // handle error(s)
> }
>
> // insert
> stmt, err := db.Prepare("INSERT INTO userinfo(username, departname,
> created) values(?,?,?)")
> res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09")
> id, err := res.LastInsertId()
> fmt.Println(id)
>
> // update
> stmt, err = db.Prepare("update userinfo set username=? where uid=?")
> res, err = stmt.Exec("astaxieupdate", id)
> affect, err := res.RowsAffected()
>
>
>    - The "watch if" would be executed after each assignment of any of the
>    variables used in SimpleStmt of the statement.
>    - Multiple "watch if" would be executed in order or appearance
>    - The "watch if" could be used like "defer..." inside functions
>    - The "watch if" would work in its full scope of the watched variables
>
> I am not a language expert, so may be there is a saner way of expression
> what I want to achieve.
>
> But bottom line is, there should by an easier to read and write way to
> deal with errors in Go.
>
>
> Martin
>
>
>
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to