if err == nil { _, err := w.Write([]byte(g.Name)) if err == nil { err := binary.Write(w, binary.LittleEndian, g.Age) if err == nil { return binary.Write(w, binary.LittleEndian, g.FurColor) } return err } return err } Why does anyone have to tell people not to do this? How does it enter anyone's mind as a thing to do in the first place? I've been known to go too far to minimize nesting. I get twitchy at the second lev…
Short circuit returns are the devil - they make it much harder to factor out part of a function into a smaller function. A function should have one entry point and one exit point; that's the whole point of structured programming. If you're going to return from some random point in the middle of your function you might as well be using goto. (Of course, good programming languages provide a better solution than pyramid…
Twelve Go Best Practices
121–130 of 153 posts
Re: Twelve Go Best Practices
#122Earlier quoted context omitted.
They allow dynamically typed methods when you need them. Why does that make you sad?
Loss of strong typing and runtime type detection is what makes me sad. Well, Go 1 has some of the problems of Java 1: no generics, typecasts from interface{} here and there, simplistic GC. Reasons are probably similar: this all is good enough for version 1, and can later be improved upon.
Except I doubt we're going to see generics in Go version 2, whenever that may be. The sentiment against it has been pretty strong in the golang-nuts mailing list.
Re: Twelve Go Best Practices
#123if err == nil { _, err := w.Write([]byte(g.Name)) if err == nil { err := binary.Write(w, binary.LittleEndian, g.Age) if err == nil { return binary.Write(w, binary.LittleEndian, g.FurColor) } return err } return err } Why does anyone have to tell people not to do this? How does it enter anyone's mind as a thing to do in the first place? I've been known to go too far to minimize nesting. I get twitchy at the second lev…
I do it in C code instinctively; it's very useful for instrumentation, debugging, and resource management in straight C to have a single return point. When I get too far to the right, that's a signal that it's time to further decompose my functions; that signal is also useful, which is another thing that keeps me doing it. But that style doesn't make much sense in Golang. It makes even less sense in Ruby and Python,…
something like:
invswitch err !=nil {
case 'err := binary.Write(w, binary.LittleEndian, int32(len(g.Name)))': return err
case _, err = w.Write([]byte(g.Name)): return err
case err = binary.Write(w, binary.LittleEndian, g.Age): return err
default: return binary.Write(w, binary.LittleEndian, g.FurColor)
}Re: Twelve Go Best Practices
#124Interesting that this snippet: func (g *Gopher) DumpBinary(w io.Writer) error { err := binary.Write(w, binary.LittleEndian, int32(len(g.Name))) if err != nil { return err } _, err = w.Write([]byte(g.Name)) if err != nil { return err } err = binary.Write(w, binary.LittleEndian, g.Age) if err != nil { return err } return binary.Write(w, binary.LittleEndian, g.FurColor) } could be written like this: func (g *Gopher) Dum…
If the language supported exceptions, how would you write this func? func (g *Gopher) DumpBinary(w io.Writer) { // Ignore all errors _ = binary.Write(w, binary.LittleEndian, int32(len(g.Name))) _, _ = w.Write([]byte(g.Name)) _ = binary.Write(w, binary.LittleEndian, g.Age) _ = binary.Write(w, binary.LittleEndian, g.FurColor) }
Re: Twelve Go Best Practices
#125Earlier quoted context omitted.
I do it in C code instinctively; it's very useful for instrumentation, debugging, and resource management in straight C to have a single return point. When I get too far to the right, that's a signal that it's time to further decompose my functions; that signal is also useful, which is another thing that keeps me doing it. But that style doesn't make much sense in Golang. It makes even less sense in Ruby and Python,…
do you know of any languages that have a sort of inverted switch statement to clean up a list of if statements like this? something like: invswitch err !=nil { case 'err := binary.Write(w, binary.LittleEndian, int32(len(g.Name)))': return err case _, err = w.Write([]byte(g.Name)): return err case err = binary.Write(w, binary.LittleEndian, g.Age): return err default: return binary.Write(w, binary.LittleEndian, g.FurCo…
Another option is monadic style, which will pass error checking along. I believe it will work well for this example, and can be implemented in Go, most likely (I don't know Go, bur it seems so).
Of course, the real problem with this code is that it is not decomposed properly. Nested error checking is the first sign of it, as somebody else already rightfully noted in the thread.
Re: Twelve Go Best Practices
#126Earlier quoted context omitted.
> Short circuit returns are the devil vi! Naïve, absolutist positions in areas of long-standing debate between programmers of great experience and the highest imaginable competence just makes you look ridiculous.
Naive, absolutist positions in areas of long-standing consensus between programmers of great experience and the highest imaginable competence makes one look even more ridiculous. By and large, the best programmers eschew nesting in favor of early returns. Invariably (in my experience) those who argue against early returns are inferior programmers (and not only by virtue of lacking taste in this particular debate).
Re: Twelve Go Best Practices
#127if err == nil { _, err := w.Write([]byte(g.Name)) if err == nil { err := binary.Write(w, binary.LittleEndian, g.Age) if err == nil { return binary.Write(w, binary.LittleEndian, g.FurColor) } return err } return err } Why does anyone have to tell people not to do this? How does it enter anyone's mind as a thing to do in the first place? I've been known to go too far to minimize nesting. I get twitchy at the second lev…
I normally see a form of it from people that don't like early returns. But if you try to do that with code that explicitly passes pack errors, you end up having to twist the code to avoid early returns. I guess this form pushes all the returns into a list at the bottom, which makes them more comfortable?
Re: Twelve Go Best Practices
#128Earlier quoted context omitted.
Less than 5% of your coworkers understand decorators? I don't want to sound snooty but this is a pretty trivial application of higher order functions.
I guess I work a lot with average developers. Not every corp is Google.
Re: Twelve Go Best Practices
#129Earlier quoted context omitted.
I normally see a form of it from people that don't like early returns. But if you try to do that with code that explicitly passes pack errors, you end up having to twist the code to avoid early returns. I guess this form pushes all the returns into a list at the bottom, which makes them more comfortable?
People don't like early returns because sometimes they return before some basic cleanup / must have function component is run. Normally added by someone unfamiliar with the function accidentally. Go's defer statement makes this much less of an issue, you bind your work piece with your defer piece so that early returns are fine.
Over time programmers have learned that one entry point, multiple exit points, is OK. But I feel that it is a good habit to flag that with a comment in capital letters so that someone skimming the code can't miss it.
Re: Twelve Go Best Practices
#130if err == nil { _, err := w.Write([]byte(g.Name)) if err == nil { err := binary.Write(w, binary.LittleEndian, g.Age) if err == nil { return binary.Write(w, binary.LittleEndian, g.FurColor) } return err } return err } Why does anyone have to tell people not to do this? How does it enter anyone's mind as a thing to do in the first place? I've been known to go too far to minimize nesting. I get twitchy at the second lev…
Because the alternative is worse. If you test-and-return after every call, your function has multiple exit points and is far less maintainable. If you nest like this, you at least have a chance of maintaining a single exit point in your function (even though this example fails to do so). This is why the Lord invented exceptions, which it seems that Go does not use. This one example is enough to convince me to never u…