Go has suffered from seen a number of Go2 error handling proposals. I'm joining the chorus as I had the feeling that a comparatively less disruptive permutation of the discussion has not come up before. I'd be totally happy if this got closed right away, in that case sorry for wasting everybody's time.
Before going to the details, I have considered:
guard in https://github.com/golang/go/issues/33161#issuecomment-512805363.try()This is an adapted version of https://github.com/golang/go/issues/33161#issuecomment-512805363, I couldn't find an original proposal to this case (/cc @carlmjohnson).
In short, I'm proposing to introduce a try keyword similar to Swift's guard that will be implemented as an error-checking and error-handling specific alternative to the existing if statement:
try must me followed by an assignment expression where the last assignment parameter must be an error and can be omittedtry statement has a handler block, the block will be executed/ the error can be handled similar to if err != nil and returned or not. This typically requires the err parameter to be named.if statement, a special scoping rule allows the assigned target variables (right term?) to escape the block (I understand this is similar to swift). This includes the error variable if it is named.As such, this proposal is similar to https://github.com/golang/go/issues/33161#issuecomment-512805363, taking the comments regarding control flow from https://github.com/golang/go/issues/33161#issuecomment-512849483 into account.
Syntactically, the two following statements are equivalent:
try foo := bar()
try foo := bar() {
return
}
It would look like
TryStmt = "try" AssignmentExpression [ Block ]
func CopyFile(src, dst string) error {
try r := os.Open(src) // returns the error
defer r.Close() // returns the error
try w := os.Create(dst) // returns the error
defer w.Close() // returns the error
try io.Copy(w, r) // returns the error
try w.Close() // returns the error
}
Update: Obviously this example needs an additional rule for error precedence during Updated the defer (tbd).defer Syntax. Using try inside deferred functions follows the same rules as everywhere else.
func main() {
try hex, err := ioutil.ReadAll(os.Stdin) {
log.Fatal(err)
}
try data := parseHexdump(string(hex)) {
log.Fatal(err)
}
os.Stdout.Write(data)
}
As @carlmjohnson said:
guard because that's a name used by another language.What are the semantics of defer try w.Close()? Does it only assign an error if the existing error is non-nil? That would solve a real problem IMO.
I think the thing that really killed the last try proposal was that it made code coverage wrongly consider a try line “covered” even if it didn’t take the error path. Is there a way to handle that for try without a block in this proposal? Maybe auto-rewrite as a return block in coverage?
I think the thing that really killed the last try proposal was that it made code coverage wrongly consider a try line “covered” even if it didn’t take the error path.
@carlmjohnson could you link that proposal? Not sure which one you're referring to- I feel it's the one I couldn't find in my research?
What are the semantics of defer try w.Close()? Does it only assign an error if the existing error is non-nil? That would solve a real problem IMO.
@carlmjohnson removed that syntax as it obscured the flow of the error variable (and if ... defer is not legal either).
I'm still not sure I get what adding some kind of try semantic to the language would solve that is not already addressed by if err != nil? One of the key strengths of go, in my opinion, is that it's strict and simple, without the unnecessary cognitive overhead introduced by offering multiple ways to solve the same problem.
it's not enough better than
ifto be adopted
I think this is exactly right. It doesn't go far enough to satisfy the people who find writing if err != nil irritating, and it's entirely unnecessary for everybody else.
It doesn't go far enough to satisfy the people who find writing if err != nil irritating
I beg do disagree. I don't think you could reduce this much more unless sacrificing other aspects:
... and it's entirely unnecessary for everybody else.
The number of error handling proposals, including those of go team members, shows that there is a wider need.
The number of error handling proposals, including those of go team members, shows that there is a wider need.
At the same time, the fact that the proposals keep getting shot down indicates that the need so far has not outweighed the added complexity.
...absolutely. And since this one doesn‘t even develop traction in terms of comments or votes I‘m simply closing it to save everybody‘s time. Thanks for sharing your thoughts!