I look at these result functions and all I can think is, "Wow, it must be really delightful when you get a zero record back and what to know why your parser has a bug." I really hope these are didactic in nature and not a representation of industry best practice.
Why not just declare a record in scope and return that? Why rely on a sneaky little piece of syntax tucked away in the return value? Aren't gophers supposed to be all about a regular language with few surprises?
> Why not just declare a record in scope and return that? Why rely on a sneaky little piece of syntax tucked away in the return value? Aren't gophers supposed to be all about a regular language with few surprises?
It's not a sneaky piece of syntax, in fact it is required to use that syntax if you want to reference or modify the return value of a function in a deferred function call.
I don't like the syntax and hate that Go forces you to use it in the above case, but it's definitely not sneaky syntax. Any regular Go developer should be expected to know about this construct.
For the most part named returns are frowned upon, and while it is admittedly an oddity in the language, having one oddity is still achieving the stated goal of "few surprises". :)
Are they actually frowned upon? I've been writing Go for a few years now and while I acknowledge there will be blind spots in my knowledge, this is still the first I've heard against using that language feature.
In fact named returns appear all over the Go source code itself[0] and the Effective Go section on named returns[1] seems positive about their usage.
Personally I use named returns heavily because it helps document what each return is used for. Which is particularly useful in IDEs like IntelliJ where you get the tooltip popup with the function parameters and returns. But frankly I find named returns just as useful when reading back old code on GitHub or even just in vi.
I also notice I'm not the only one who uses them in production code. Here are some popular packages by other talented Go developers (all .go files picked at random)[2][3]:
"Are they actually frowned upon? I've been writing Go for a few years now and while I acknowledge there will be blind spots in my knowledge, this is still the first I've heard against using that language feature."
/r/golang consensus is against using named values. I disagree with it, but the consensus is there. Or at least I think that at the very least named return values should indicate that someone is doing something with a defer.
As for why, I don't get a clear sense. I hate to characterize an argument I disagree with, but I have to admit I just sort of get the sense that it was one of those things that just sorta happened. Sometimes one person says something, another person half-heartedly agrees, and before you know it it's getting parroted around by an entire community. I acknowledge again that as I don't agree with it this may be a rather harsh read on my part.
> /r/golang consensus is against using named values.
/r/golang is a toxic subreddit and I wouldn't take anything said there for face value. Dave Cheney deleted his account there and the go team itself wanted to delete that subreddit. So no, /r/golang represents only /r/golang and certainly not the go community as a whole.
/r/golang favorite pass time is to take some piece of code or a library and humiliate its author(s) publicly for not writing go like /r/golang wants go to be written.
Dramatic much? There's nothing "toxic" about /r/golang. It's mostly boring content, and the criticism is rarely worse than what's going on in this very thread (which is itself mild by HN standards). The official rationale for why Dave and the Go team left has changed several times, but it has always been over-dramatic or vague (e.g., "We need to shut down /r/golang because the CEO of reddit might edit our posts like he did with /r/The_Donald!"). At any rate, their opinions of /r/golang don't make it toxic, and /r/golang is a reasonable approximation of the broader community's opinions--at least as good as anywhere except maybe the mailing list.
"and the criticism is rarely worse than what's going on in this very thread (which is itself mild by HN standards)."
I'll echo that. If /r/golang is "toxic" this HN conversation is outright radioactive. This is far worse than any day-to-day thread on /r/golang.
As I understand it, the basic reason the Golang authors themselves decided to leave wasn't the "golang" part of "r/golang", but the "r" part; Brad Fitzpatrick, having run LiveJournal, was incredibly and IMHO justifiably offended by the revelation that Reddit admins had been editing people's posts, because of his personal experiences and ethics. It also turned out that the Golang people had not started the community, but accidentally thought they owned it none-the-less, which IMHO puts a new light on how the /r/golang community reacted when the Go authors attempted to lay down rules on how it works. Of course the community reacted poorly to what amounted to people just dropping by and asserting tons of ownership over the community they hadn't created and only marginally participated in. Nobody should expect that to just go swimmingly. But at the core it was all a misunderstanding as to who owned the community, which has since been resolved.
The fact that go maintainers themselves wanted to get rid of /r/golang actually proves otherwise. As for Dave Cheney, he left that sub long before any Trump drama on reddit.
Obviously the people who act in a toxic fashion don't think themselves as such and don't see the toxicity even when it blatantly exists.
But that's not my point. /r/golang is officially outside Go community since even go maintainers disowned it and want nothing to do with it. Whatever drama happening there is not representative of the go community, nor whatever /r/golang thinks as "idiomatic".
It doesn't "prove" anything. It only proves that the maintainers are intolerant of the community, for whatever reason.
> Obviously the people who act in a toxic fashion don't think themselves as such and don't see the toxicity even when it blatantly exists.
Maybe I "act in a toxic fashion" or maybe your standards for "toxic" are just extremely low. Fortunately, we don't have to agree on the absolute threshold for toxic, we can make relative comparisons; as /u/jerf stated, if /r/golang is toxic, this thread is radioactive. Anyway, it's rude to make unfalsifiable implications about other people, or to speak as though your own subjective thresholds are absolute ("...toxicity even when it blatantly exists"); and it's foolishness when your own standard for "toxic" is so much lower than the common use.
> /r/golang is officially outside Go community since even go maintainers disowned it and want nothing to do with it.
You're confusing the Go community with the various subcommunities under the maintainers' moderation. You have to provide a better rationale for why /r/golang is an invalid sampling of Gophers for the purpose of named returns; "because the maintainers don't like it" is not very compelling.
> It doesn't "prove" anything. It only proves that the maintainers are intolerant of the community, for whatever reason.
Wow. What a way to prove the parent's point.
>Maybe I "act in a toxic fashion" or maybe your standards for "toxic" are just extremely low.
Honestly, you appear to make it your own personal point to act like a dick, and for no reason at all. That's very toxic, and in a very needless manner. If your behavior is any indication of what goes on in /r/golang, no wonder relevant people decided to abandon it. There's nothing to be gained by sticking around people who make it their point to act like dicks.
You can think what you like. My post wasn't defensive or vague, but then again who can disprove accusations about their motives? The OP was criticizing a community I don't belong to, and which I even criticized in the post above; so you can believe me if you like or not. As for "vague"; it's hard to be too specific when the OP would only speak about unqualified "toxicity".
A couple of months ago I had someone on /r/golang taking credit for one of my own projects. I just ignored him and took it as a compliment but now I'm not sure if that's an insult (jk)
Disclaimer: I don't follow /r/golang. I was looking at Github traffic and noticed quite a few requests with Reddit as their refer(r)er.
I think changing the behavior of the return keyword is a bit worrisome given the often long nature of Go functions.
The way return works is dictated by the existence of a perhaps bad name in the start of the function declaration, in a place most likely to fall off screen in a split editor scenario.
I called it sneaky because I think it's hard to see. I don't get the value of this technique over, say, naming and returning locals. Certainly from a performance perspective it will be identical.
It doesn't change the behavior of the return keyword, though. It adds a case, but it's an orthogonal case; if you have a function that returns anything, a bare return can only be using the named return values.
My position is that I'm OK with saying "only use this if you need to screw with the return values via defer, and thus, the presence of named return values can be reliably inferred to mean that someone is using defer to change the values", but to say "They're always a bad idea and never use them." is way too strong and dogmatic. They're in the language for a reason, because otherwise errors in defer statements could only be A: ignored or B: panic'ed, which is a far bigger problem in reality than the named return parameters.
Without a named keyword, a void function can use the return keyword to terminate control flow conditionally. So it's only orthogonal in the case of a function with a typed return value.
Which is fine. I have no problem with it. I'm a Haskell/ Clojure/Erlang/TypeScript/CL developer, so I'm used to this. But golang users beat me over the head with the "simplicity" of Go and use examples of Haskell and Clojure having lexical scopes change common keywords as examples of the "excessive complexity of !Golang".
I'm not asking you to defend an argument you didn't make, but I think Go folks need to own that this is actually a code smell for something that could be done differently a scoped variable.
I feel some of the criticisms for this feature are a little exaggerated. I mean comments like "Also my hair gets paler and my body grows weak thinking about using defer with named return values" are borderline silly. Opinions of named returns aside, they're really aren't that hard to follow. Or at least if your function is genuinely that complex that you have a physical reaction when trying to parse a function with a named return then I'd suggest that function needs more refactoring beyond the initial critique.
A few direct counterarguments:
* Named returns doesn't change the nature of the return statement. In fact you can still use return with locally scoped variables even with named returns (example below).
// This is only an example of overriding the default return.
// I'm not suggesting people write code like this!
func StrToBool(s string) (b bool) {
if s == "true" {
return true
}
return
}
* "often long nature of Go functions" is purely a developer style. I prefer the methodology of breaking functions down to small logical units. Sure sometimes the cleanest code is a long function. But most of the code I write and collaborate with is more around 20 lines or less.
At the end of the day named returns do provide some benefit eg when writing public APIs so other users can see - at a glance - what inputs and what returns a particular function takes. But like any feature in any language, a bad developer will easily find ways to abuse it.
> I mean comments like "Also my hair gets paler and my body grows weak thinking about using defer with named return values" are borderline silly.
I regret my deliberate silliness only reaches "borderline" with you. Do I also need a unicycle. What does it take?!
> StrToBool
Make this function 30 lines long, take 6 arguments and then you have my original argument. It creates context sensitivity, something Golang tries not to do.
> But most of the code I write and collaborate with is more around 20 lines or less.
I'm tempted to write a github crawler to work this out. Golang is C-like in that its lack of reuse capabilities incentivize longer functions or copypaste functions.
I'm simply against this kind of context-sensitivity in a language that prides itself on being reader friendly. It's not. Let me rephrase my argument.
Question:
return a; // What does this do?
Response: It returns the value at a. I don't know what that value is, but it must be a local or a function parameter. This function definitely returns a value, one value.
Question 2:
return; // What does THIS do?
Response: Well... all I can say with confidence is that this returns, the functions execution will end. But I can't tell you if it returns nothing, or a value, or how many values.
The existence of this makes bare returns much more confusing than... well... I struggle to come up with a syntactical convention in Golang that can do this. I haven't written Go for reals for 2 years so maybe you have something better.
To me, this is way worse than even the "worst case" Haskell scenarios where your code only makes sense in the context of its caller.
> Make this function 30 lines long, take 6 arguments and then you have my original argument. It creates context sensitivity, something Golang tries not to do.
But like I said before, you're blaming unclear code on the language rather than the developer. It's an optional feature, so don't use it in inappropriate situations.
It's like the whole goto statement argument. Nobody is suggesting we all using goto's just because the feature exists. But very occasionally it does produce cleaner code. Yet you still get an army of evangelists who argue that "goto" should be stripped from every language specification written since the 80s.
I've read a lot of other people's code. Particularly the Go source code itself - there's named returns all over the place there. There are also some quite long and complicated functions too. The use of a named return has had a negligible impact on my ability to parse a function compared to any of the other inherent complexities that function exhibited. ie I followed that code just as easily than if those returns were not named.
Which is why I keep coming back to the "You're points are not wrong per se but they are greatly exaggerated." arguement. But like nearly all arguments about language semantics and syntax, developers love to argue how their personal preferences are conclusive scientific facts. Ironically spending more time trying to prove our points online than we actually spend affected by the problems we're arguing about.
So yes, you are not wrong per se. But you are greatly exaggerating the issue.
> But like I said before, you're blaming unclear code on the language rather than the developer. It's an optional feature, so don't use it in inappropriate situations.
There's a 30 line function claimed to be a refactor of production code in the article we are discussing. It's not my whole cloth example. Heck, my first post was commenting on the structure of that very function hoping it was a defactoring example. People have chosen to focus on the other point in that post.
> So yes, you are not wrong per se. But you are greatly exaggerating the issue.
I understand what you're trying to do but I'm pointing to the overarching article. I didn't make this scenario up.
Also, the personal context I bring here is how many lectures I get from anti-haskell-pro-Go people lecturing me about simplicity, obviousness, etc ad nauseum about why I should adopt their language. So if you're detecting a bit of frustration here at a double standard, I do apologize.
Yeah, the article wasn't great. I think few supporters of named returns would even agree with that article.
Like all language features, you're always going to get some individuals who will misuse them. The author there I definitely think is misusing named returns for something that really needs to be optimised in the compiler instead.
In defense of the article, I can see how anyone writing a lot of Go would start to get a bit desperate for shortcuts. It's a language that's relentlessly hard on prolific writers, putting their needs second in favor of minimizing the context required for any code.
So I could see how things like having a alternative-providing validator chain take 5% fewer characters would feel intoxicating after using code generation to stamp out four variants of a competent data structure for some primitive types.
One minute you're moaning that features need to be removed from Go, the next you're mocking it for not having enough features. Yet you dont even code in the language you're clearly very opinionated and highly critical over.
We all have our personal preferences, I get that. But why can't people just live and let live instead of trying to make out their personal preferences are measurably better than those they dislike? After all, if all programming languages were identical then the IT industry would be worse off for it.
For what it's worth, I've been writing software for nearly 3 decades now and have writing applications in well over a dozen different languages. Go might lack some of the expressiveness I'm used to but it's still one of the most rapid languages I've used to create software. And one of the most painless to deploy too. In fact ironically some of the "worst languages" in terms of developer chin stroking have been some of the easiest to work with; Visual Basic (pre .NET) is another example. But if I had my way we would be back to writing DOS programs in Turbo Pascal. This is why I get so fed up with people moaning about their tools. Frankly put, mocking any particular tool for not behaving like another particular tool just shows ones own limitation as a developer.
> But why can't people just live and let live instead of trying to make out their personal preferences are measurably better than those they dislike? After all, if all programming languages were identical then the IT industry would be worse off for it.
I enjoy programming in Go about as much as I enjoy wearing shoes about 3 sizes too small. As a result, it's my goal to find very good arguments against its use in any of my projects. Should I feel bad about this? If so, can you come and stop people from powerdunking on me every time I talk about how Haskell is good at something?
I'm not mocking Golang here. It is what it is. I think it's an oddly designed tool based more around making Google's turnover easier to deal with rather than helping me as a software engineer. I am expressing frustration at people who want to laud its design as "good" or "progressive" or helpful when really, it's the language equivalent of a querty keyboard layout. Designed to be about as easy to learn as anything but prevent anyone from getting excessively good with it, because large skill gaps in a workforce with turnover are hard to manage around.
The Go code review document gives a brief comment about when they like and don't like to use them[1].
Personally the only time I find them to be acceptable is when you have to reference a returned value in a defer. All other usages are questionable, though this is a taste thing and is likely because of my dislike in it's usage as a way of omitting a `var` in a function body (and also the fact that naked returns are magical in comparison).
I don't think naked returns are any more magical than when you just drop a variable name in there. Either way, when you read a return statement you'll want to re-read the code to find the context of that return. The only difference is with named returned the variable is declared in the function declaration rather than the body of code. So it's definitely just a preference thing there.
My coding style is to try and avoid lengthy functions -
my procedural code is definitely inspired by the functional paradigm. Granted it's not always possibly to avoid a long function but for the shorter ones named returns tend to produce cleaner looking code _in my opinion_.
In any case, I will definitely take your points on board and be more mindful about when using named returns - ie think about whether they're adding to the readability or if I'm just being lazy saving myself a var declaration. Thank you for the reference article as well.
> Either way, when you read a return statement you'll want to re-read the code to find the context of that return.
That's the ugly part of this feature. It adds one more place where you need to check.
Also my hair gets paler and my body grows weak thinking about using defer with named return values. Isn't Go supposed to easy to read? Isn't that like it's principle virtue?
Eh, I've heard this a few times; I thought once from Francesc Campoy, but maybe I'm wrong? I don't feel strongly about them, I was just repeating what I heard.
The rationale was that they can make code hard to follow, especially when one of the returns is err and you have other errs in your function.
Lastly, to be clear, I didn't mean to imply they were frowned upon in all cases; only that you should prefer normal returns unless you have a compelling reason.
Definitely agreed. Since getting into using Gogland (the JetBrains Go IDE), I'm using named return values much more because the name is useful in the pop-up help. I don't need to look up function docs anywhere near as often.
Why not just declare a record in scope and return that? Why rely on a sneaky little piece of syntax tucked away in the return value? Aren't gophers supposed to be all about a regular language with few surprises?