> Most functions are called more than once in a program, so adding > context to the implementation itself would benefit every caller: they don't > need to add the context themselves.
This is highly questionable assumption. Context outside is obviously superior: - Your assumption just does not work. Imagine a generic function like *os.Open*, it cannot provide really sensible and easy to read context. - Context outside means finer control, the annotation can tell exactly what you meant. With *try* you only can achieve the same with numerous tiny functions of one use and this payload hugely overweights these *if err != nil* I really glad this strange proposal was rejected. I was voting for better error handling, but I meant better error handling, not this nonsense. I would like to have something that will not allow to pass error handling by mistake, not the way to save 3 or 2 lines of code in one place just to have additional 6 lines to achieve the same error annotations detais. среда, 29 июля 2020 г. в 01:01:34 UTC+3, mbohu...@gmail.com: > I've been thinking a lot about this Russ's comment > <https://github.com/golang/go/issues/32437#issuecomment-503297387> from > the try > proposal: > > > But before we get to try, it is worth making sure we're all on the > > same page about appropriate error context. The canonical example > > is os.Open. Quoting the Go blog post “Error handling and Go”: > > > > > It is the error implementation's responsibility to summarize the > > > context. The error returned by os.Open formats as "open /etc/passwd: > > > permission denied," not just "permission denied." > > > > See also Effective Go's section on Errors. > > Specifically, this quote: > > > There is lots of code following the Go convention today, but there > > is also lots of code assuming the opposite convention. It's too > > common to see code like: > > > > f, err := os.Open(file) > > if err != nil { > > log.Fatalf("opening %s: %v", file, err) > > } > > I'd say, from the comments on the try proposal and other proposals > related to error handling, as well as from various different blog posts > and podcasts, that there's more cases that follow the *opposite* > *convention*, i.e. it is the caller rather than the implementation that is > adding context. > > Most functions are called more than once in a program, so adding > context to the implementation itself would benefit every caller: they don't > need to add the context themselves. > > This brings me back to the try proposal, which, as far as I know, > was trying to solve the most common problem: removing boiler plate > code when the caller has no additional context to add. In my estimate, > this is roughly 50 % of the cases in a typical codebase. A number > of commenters were arguing that the try proposal doesn't make it > easier to add context to the error, but that wasn't the problem it > was trying to solve. It's already quite easy to add context on the > caller's side: just use if/switch statements or other mechanisms. > (Errors are values.) > > So despite being sceptic at first, I ended up being in support of > the try proposal. It solves the biggest issue with error handling, > and it solves it well. Specifically it: > > 1. encourages the right convention to add context on the callee's side, > 2. and makes the code more clear and expressive for roughly 50 % of the > cases. > > In my view, the only valid arguments against this proposal were outlined > in the > decline comment > <https://github.com/golang/go/issues/32437#issuecomment-512035919> by > Robert: > > > As far as technical feedback, this discussion has helpfully identified > > some important considerations we missed, most notably the implications > > for adding debugging prints and analyzing code coverage. > > As I see it, the first step in the journey to better error handling > is to make most Go code agree on which convention to use: whether > it is the implementation, or the caller who is responsible for adding > context. > > -------- > > Since the recent changes to the Generics proposal make it more > realistic that Go might one day get generics, I was thinking whether > the try proposal could be implemented using them. This is what I > come up with: > > // Package eh implements functions for error handling. > package eh > > func Check(err error) { … } > > func Try[type T](v T, err error) T { … } > > func Try3[type T, U](v T, w U, err error) (T, U) { … } > > func Catch(errp *error) { … } > > func Catchf(errp *error, format string, args ...interface{}) { … } > > 1. First off, the package name should be short since the package > would be used a lot in practice. > 2. We don't need that many variants for the different argument > counts: most functions returning errors return 2 values. There might > be some with 3 values. We might add Try4 or even Try5 if that would > prove to be useful. > 3. The name Check seemed to fit better for error-only checking. > 4. In order for this to work the package would need to use panic; > thus, every function using this kind of error handling would *need* > to defer calling to either Catch or Catchf. This would probably > require some sort of vet check to prevent misuse. > 5. This package combines variants of the proposed built-in function > "try" as well as the helper methods as proposed by Russ in > https://github.com/golang/go/issues/32676. I chose Catch and Catchf > without further consideration; that's not the point of this post. > > Some examples derived from the try proposal: > > func CopyFile(src, dst string) (err error) { > defer eh.Catchf(&err, "copy %s %s", src, dst) > > r := eh.Try(os.Open(src)) > defer r.Close() > > w := eh.Try(os.Create(dst)) > defer func() { > w.Close() > if err != nil { > os.Remove(dst) > } > }() > > eh.Try(io.Copy(w, r)) > eh.Check(w.Close()) > return nil > } > > func printSum(a, b string) (err error) { > defer eh.Catch(&err) > x := eh.Try(strconv.Atoi(a)) > y := eh.Try(strconv.Atoi(b)) > fmt.Println("result:", x+y) > return nil > } > > There are really 2 questions I want to ask: > > 1. How to motivate people to use the Go convention (let the > implementation add the context). Is that the right convention? > 2. Do Generics enable implementing a package for try-like error > handling, or am I missing something? > > -- 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. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/f4f6e332-e22e-4170-8c56-2dedd4f38336n%40googlegroups.com.