It's kind of satisfying to see that the "Go way" wasn't the best way after all and that some of these things are actively being addressed. I hope it makes the community a bit more welcoming as well.
Sometimes this is just due to defensiveness: someone uses a flaw to say the whole language is terrible and that gets a response from people who have learned to live with the flaw.
Generally, if you back to the original statements you'll find something more nuanced: generic types have a lot of complicated effects on language design and they didn't like their own early proposals, so they started out without them. Yes, error checking can be repetitive, but many of the attempts to fix that in other languages were worse.
In the meantime, the "Go way" is about following common conventions for working within the language's limitations. This isn't a bad thing!
But it's tricky to be welcoming while getting across that the best way to deal with limitations is just to accept them, for now. On the Internet, everyone wants to be Steve Jobs and demand changes.
(Also: Rob Pike, not Erik.)
I think they’re onto something, though as the GP notes, hopefully the situation is improving.
I’d flip your response around and suggest that in several cases, the correct fix is obvious and the core Go team’s insistence on extreme caution and “nuance” is misguided. GOPATH is a great example -- it’s just so obviously wrongheaded that I really don’t understand why it stuck around so long.
Another one that comes to mind, although this is quite old now, is the way early versions of Go would insist that the very last statement of a function was a “return”; you couldn’t do an “if foo { return x } else { return y }”, for example. It took a lot of pushing to persuade the core team to add some basic escape analysis, against insistence that it was some kind of nuanced feature with unpredictable side-effects, rather than a trivial thing that every other real compiler has to do.
Except the problem is that "the Go way" changes in a way that breaks your previously-"working within the language's limitations".
An example of this that comes to mind is how the Go 1.5 vendor/ change was done. The community had rallied around several tools that would do vendoring and then would modify GOPATH to include vendor/ and would then symlink the current project into vendor/. All this required was a vendor/src. The Go 1.5 vendor/ implementation was almost identical but they removed the src directory -- which meant that pre-1.5 vendoring was now broken by Go (you can't really have two copies of your vendor tree in a repo and symlinks wouldn't work either).
There are a few other examples of this, but this one sticks out as it was the first feeling I got that the Go development team doesn't really care how the community has decided to work around a language defect. It literally would have just taken them one additional directory to not break every vendor/ project.
(Also, there has been absolutely no discussion with distributions -- as far as I'm aware -- on how packaging Go binaries should be done so we're all forced to come up with our own ideas. The Go modules stuff has considerations -- like builds requiring an internet connection -- that distributions would've had input on, but we didn't get asked about it.)
My favorite example here is this arrogant dismissal of the idea that a one line expression, rather than a 5 line mutating statement, might be preferred for conditionally setting a value:
if expr {
n = trueVal
} else {
n = falseVal
}
> The if-else form, although longer, is unquestionably clearer. A language needs only one conditional control flow construct. [0]...
n = expr ? trueVal : falseVal
"Unquestionably"&&, ||, switch, select, for, and while all do conditional execution in Go.
So the rule is not "A language needs only one conditional control flow construct." The rule is really, "We didn't think a conditional operator was worth it." That's a fine rule, but it's better to be honest about it than to pretend the language was designed around some pure principle that doesn't actually exist.
This isn't an insult to programmers, it is an option that clarity of code is more important then continence. Thus all if and for statements also require {} brackets.
I was thinking I could write my own if(condition, true_case, false_case) method similar to the way it's done in spreadsheets, but Go also doesn't have macros or inline if/else expressions, so there is simply no way to emulate ternary logic in a performant manner :-(
n = if(expr) trueVal else falseVal
No need to learn a separate ternary operator.If by "one" you mean `if` _and_ `switch` then yes!
Most everything I've seen from the Go camp, including the new re-discovery of various wheels with the Go 2.0 proposals, felt like the parent describes to me.
Never got the same from Rust, otoh.
> pretty much every Go-related conversation over at /r/programming seems to have someone arguing that it's literally impossible to build software in a language that lacks generics
Literally literally? Isn't your reply a "bad way to characterize the overall conversation" as well?
Generics is a major tell, too, since the Go team's position on generics was always "generics are interesting but we don't know how to make them work well with Go's existing type system". See for example, this blog post from 2009: https://research.swtch.com/generic which references the FAQ answer to the generics problem here: https://golang.org/doc/faq#generics: "Generics are convenient but they come at a cost in complexity in the type system and run-time. We haven't yet found a design that gives value proportionate to the complexity, although we continue to think about it."
so I can see why people who have repeatedly answered the same question for years, only to have their answer misrepresented for years, to be annoyed when people who haven't read any prior discussion bring up a point that has been already talked about ad nauseam.
It was a comment on my personal experiences of interacting with the Go community, not the language and its limitations. My hope wasn't that Go implements my every pet peeve, my hope is that the community has gained some humility since I last dipped my toes in it.
Pike seems especially aggressive when interacting with people he disagrees with and this was for me indicative of the culture. It's been a few years though, so maybe by now I'm wrong!
Here's Pike on the topic of syntax highlighting:
https://groups.google.com/d/msg/golang-nuts/hJHCAaiL0so/E2mQ...
There were 22 comments, and the one from the Go developer was (and I quote):
"Tempted to stop reading after the first word in the article. (The language isn't called Golang)"
Frankly, it's just tiring; especially as a lot of the same points and misconceptions are repeated. Some points are valid, but it's repetitive at best. It would be like discussing Python's significant whitespace with inexperienced Python programmers every week. Sure, it's quirky and arguably not a good idea, but the discussion had been done a few times already.
Turns out that filtering stuff that uses "golang" instead of "Go" is actually a pretty good heuristic for determining if an article is worth reading. Is it perfect? Of course not; it's a heuristic.
Reading your article, this is exactly the sort of "been there, discussed that" kind of example. Your article isn't bad – I think it's mostly on-point – but it's also pretty much a repeat of what many others have said/discussed.
Given that, they do also 'talk down' in their official documentation. I had to look back in time to understand the memory model for the sync.atomic operations which is documented:
"These functions require great care to be used correctly. Except for special, low-level applications, synchronization is better done with channels or the facilities of the sync package. Share memory by communicating; don't communicate by sharing memory."
The final word on what 'great care' means is that Go doesn't actually have a memory model for this part of the standard library. The discussion thread around it has a different tone than the official documentation. They agree on how they want implementations to operate, but don't feel that it needs to be officially defined or documented. I would have been happy if they at least referenced the discussion thread rather than merely label it 'great care' meaning 'not for you'. The other thing you find is that the performant parts of the standard library often does not follow "Share memory by communicating; don't communicate by sharing memory".
One of the betrayals when working with I/O was finding that standard library routines can return a value AND an error, and that sometimes a non-nil error is not an error (EOF is not the only one of these).
CLASSPATH, PYTHON_PATH, PERL5LIB, ...
I never really understand the hate here. It seems more like they didn't hate GOPATH specifically and more that they didn't like not having a package manager.
Go solves Googles main problem -> something which new engineers can use to write practical solutions without having to think too much. It's not beautiful or expressive or technically interesting; most "craftsman" devs won't stick with it too long..But that's not the majority of devs google is hiring.
Sit down, bang out code and don't concern yourself too much with craftmanship - it will be re-written in a couple of years. Just worry about performance.
My primary use case is scientific computing, both data processing and interactive visualization.
I know Julia is an option as well.
For reasons I don't want to bother getting into I dislike Python.
Thoughts?
I use and like Go for writing network servers and ETL processes. In a scientific context though, the type system is awkward in the extreme, there is essentially no library of modules, and the interactive visualization story is nonexistent.
Python, R, Julia, even C++ would be better options IMO.
(I'll clarify again: I like Go! I just think it's not well suited for this context)
[1] https://oracle.github.io/graphpipe
[2] https://github.com/oracle/graphpipe-go/blob/master/helpers.g...
generics may help in that department.
in the meantime, there's Apache Arrow:
If you actually have a primary use case of "scientific computing, both data processing and interactive visualization", ignore Go.
And rethink Python.
Julia can be used, but is still fringe.
R perhaps.
Gonum is almost on par with _e.g._ NumPy/SciPy (most notably lacking: ODEs). So still ways to Go but it's getting there.
Go-HEP is my attempt to bring a few High Energy Physics oriented packages to particle physicists:
I've also written a few words on why I think Go is great for science:
- https://sbinet.github.io/posts/2018-07-31-go-hep-manifesto/
TL;DR: Go is great b/c it brings great s/w engineering practices and a s/w engineering-friendly environment to scientists.
Admittedly, generics will change how packages are written. So some code churn will take place when/if they land, but the Go community learned the lessons from Python2/3 and Perl5/6. Expect a better migration path.
Lastly, I guess the 2 remaining weak points of Go are:
- runtime performances sub-par wrt C++ or Rust
- GUIs (which may or may not fall into "interactive visualization")
That said, the Go community worked on a Go kernel for Jupyter:
- https://github.com/gopherdata/gophernotes
hth, -s
Beyond that, Go is easy and performant. It's great for paralellizing workflows via concurrency and compiling tools for distribution. So if you know what you want to do and need to scale up, it could be a great choice.
- neugram.io
- https://github.com/cosmos72/gomacro
here is a mybinder that used to use the former, and now uses the latter:
I am glad to see that the go team is working on cleaning up the tooling situation. I used gocode, then started using modules, found that the primary version was unmaintained, and had to switch to a different fork. I believe I also needed a different version of goimports for a while. Having all this tooling unified into the langserver maintained alongside go sounds wonderful. I hope other languages do the same thing.
So instead of creating M packages * N OSes, we do it just once.
For non-go tools like the protoc compiler I don't think the golang tooling provides any help. A heavyweight option would be a build system like bazel
- https://github.com/golang/tools/blob/master/cmd/golsp/main.g...
I regularly find myself in a position that this system would make impossible: I need a few custom changes in public available libraries. An extra method. A bugfix. What have you. This makes that impossible using the default method.
What we want is consistent builds. That means a build that happens, with the same source, with the same ... every time, always, on everybody's workstation.
If I want to share things, I am aware of links in filesystems, thank you very much Go authors. "go.mod" overrides ... I wish golang did not try to solve yet another non-problem badly.
All the infrastructure with index, notary, mirror, etc. is nice, but at the end of the day you have to fetch some external code, verify it, lock it down in some vendor directory, and check it into your own backed up repo. Everything else is fluff.
If you're not doing this you're dancing with the devil and one day when you need to tweak some module or fix some bug, and the remote source is long gone, you will rue the day you depended on anything except your own source storage. And it will be 3 AM on Saturday, in some dismal server room, with no outside Internet connection, your customers screaming at you, and your phone battery dying, because Murphy's law.
For the purposes of software builds just pretend the rest of the Internet does not exist. Vendor everything, all the time, everywhere, and trust nothing.
This whole gopath-less thing is a bit confusing to me. I wish the 'how to use packages' stuff was clearer.
Decentralized support has been a thing since the last decade.
I think decentralized is meant as "there's no central repository" here.
That's one of the things I like in go most. Having decentralized packages via domains and URLs and then index them (godoc.org works very well), it mirrors the design of the Web. In contrast npm, Rust and others that are tightly coupled to one site feels like Google AMP - centralizing and hosting everything in one place.
> that anyone should be able to publish their code on any server, in contrast to central registries such as Perl’s CPAN, Java’s Maven, or Node’s NPM. Placing domain names at the start of the go get import space reused an existing decentralized system and avoided needing to solve anew the problems of deciding who can use which names. It also allowed companies to import code on private servers alongside code from public servers.
lol statements like this are infuriating. Go is no more decentralized than those languages, unless you consider git hosting something people in standard practice do on their own (survey some of the top Go dependencies and see if that holds true). They simply lack a package index, but the cited language package managers both have those and allow you to host your own.
I think that having a system in place with the language may be a better option than a company with its' own motivations and needs separated from the language/runtime/platform.
As to generics, I think you may well find generics in the future. I feel that most of the resistance was in order to better support core language features. I can't think of any languages (I'm no expert) that started with generics support, so I'd be surprised if this wasn't a go 2.x goal.
For exceptions, I think that the go solution works. Similar to the callback interfaces in node, it puts errors in your face, which isn't a bad thing. I mainly contrast this with node, as it's another language/platform that has grown a LOT but also relatively recent.
You can compare the progress of node, go and others to say python2/3, C#, Java and others. I think go progress has been great by comparison, and pragmatic choices have ruled out.
It didn't take "this long"; the Go team openly admitted the need for a better approach at the very first GopherCon back in 2014, nearly five years ago. (That was not the first time, either).
It takes time to do all that work.
(As a side note, I don't think there are any plans for exceptions -- for good)
Also, https://go.googlesource.com/proposal/+/master/design/go2draf...