try
keyword.This isn’t a complete proposal it only describes basic idea and the changes suggested.
The following are modifications that deals with some of the problems introduced in the original proposal.
(I apologize if something very similar that uses a simple method to deal with adding context has been posted before but I could not find it.)
First, try
is a keyword not a function builtin.
Here’s how error handling with the try
keyword works:
try err
is equivalent to:
if err != nil {
return err
}
That’s it.
Example:
f, err := os.Open("file.dat")
try err
defer f.Close()
f.WriteString("...")
because try
only returns if err != nil.
You can create a function that returns nil
if an error is nil
.
In fact, a function like this already exists in the errors package here.
https://github.com/pkg/errors/blob/master/errors.go
// Wrap returns an error annotating err with a stack trace
// at the point Wrap is called, and the supplied message.
// If err is nil, Wrap returns nil.
func Wrap(err error, message string) error {
if err == nil {
return nil
}
err = &withMessage{
cause: err,
msg: message,
}
return &withStack{
err,
callers(),
}
}
Example using it with try
f, err := os.Open("file.dat")
try errors.Wrap(err, "couldn't open file")
defer f.Close()
f.WriteString("...")
That’s it.
This should reduce repetitiveness with error handling in most cases.
It is very simple to understand, and it feels like Go.
I agree,
Some of the proposals introduce more trouble than the problem they are solving. For example, the proposed try works only iff you are returning a single value of type error. If you have more return values what happens?
--
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...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/8584ff0d-deb1-483a-b152-45639a4ce088%40googlegroups.com.
f, err := os.Open("file.dat")
try errors.Wrap(err, "couldn't open file")
[sorry, posted a half post before]
I think the keyword we are looking for is `pass`. Similarly, `pass` only needs to return if err != nil.func writeSomething() error {f, err := os.Open("file.dat")pass errdefer f.Close()f.WriteString("...")}---passing a wrapped error(using the Wrap function above which returns nil if err is nil (not a special function) ):func writeSomething() error {f, err := os.Open("file.dat")pass errors.Wrap(err, "couldn't open file")defer f.Close()f.WriteString("...")}
No, 'pass' accepts an error type. in this case Foo function must return an error type otherwise that would be a compile error.
I already said, multiple return values are supported (the original proposal also handles this) otherwise what's the point?. You can do this:func doSomeTask() (int, bool, error) {f, err := os.Open(filename)pass errdefer f.Close()....return 10, true, nil}
On Saturday, 8 February 2020 10:33:03 UTC, addi t0t08 wrote:No, 'pass' accepts an error type. in this case Foo function must return an error type otherwise that would be a compile error.Ah I see: you are relying on the behaviour of errors.Wrap(nil, "dontcare"), which is valid and returns nil. That's a bit of hidden magic.
pass nil
pass errors.New("some error")
- What would "pass" return for the int and bool arguments - the zero value for each perhaps?- What would it do instead if these were named return values? Would it return the values already assigned, or always zero values?To me, this seems to be hidden magic, when compared with the original if statement, which has absolutely unambiguous semantics.
Aside: I suppose it's worth mentioning that in principle golang lets you do this:if f, err := os.Open(filename); err != nil {return 0, false, SomeError}However, this form isn't as useful as it first appears, because "f" drops out of scope after the "if" statement. You can put the rest of your code inside an "else" block; or you can pre-declare your variables before the "if" statement. Either way is more work than it saves.var f, g *os.Filevar err errorif f, err = os.Open(file1); err != nil {return 0, false, SomeError}defer f.Close()if g, err = os.Open(file2); err != nil {return 0, false, SomeError}defer g.Close()
... etc
f, err := os.Open(file1) ; pass err
defer f.Close()
g, err := os.Open(file2) ; pass err
defer g.Close()
.....
Also, without any additional changes to the language. Go already allows separating statements with semicolons, so it would be even possible to do the following.
f, err := os.Open(file1) ; pass err
defer f.Close()
g, err := os.Open(file2) ; pass err
defer g.Close()
.....