Why Go is doomed to succeed
texlution.com
texlution.com
Because the Unix system programming world (and POSIX particularly) is very much built with the conventions and semantics of C in mind, most serious POSIX programming outside of C means you have to deal with painful FFIs, lousy wrappers, overly abstracted APIs that hide details like certain lower level flags and so forth. Some are better at this than others, of course (OCaml is one of the better ones)... but, nonetheless.
So it's unsurprising that many infrastructure developers are jumping to Go. There's just enough new things to incentivize a switch, but not too much that it dissuades from it.
When I jumped ship from C to Java, Java's object orientation wasn't exciting to me, and its exception handling is an acquired taste.
But dynamically growable, garbage collected buffers are something I'd missed for a long time. And the simple ability to concatenate strings without first reserving space for the result. Oh, and hash maps! Remarkably versatile data structures, those.
Coming from C, Java was a delight. Java would have a lot more trouble dragging me away from Go.
Also, having a map implemented in a library is a Good Thing. It means that your language is extensible and expressive enough for this. AFAIK Go is - by design - not that extensible.
Auto-conversion: "2" + 5 = "25". This looks horribly hackish, like some type buggering perl might do, or js. But it comes in handy when you want to build a message string.
And yes, as the article tells us, a lot of things are very purposely left out of Go, which has advantages and disadvantages like most trade-offs.
string hello = "hello";
string world = "world";
string hw = hello + ' ' + world;
Auto-conversion: stringstream ss;
ss << "2 + 2 = " << 2 + 2 << endl;
string result = ss.str();"nice try" on "auto-conversion".
C++11 has a GC API defined.
Reference counting is part of any GC book in CS speak.
However, I feel that doing the "implicit casting" thing only for the single, limited case of string concatenation strikes a happy medium between providing useful convenience and giving you enough rope to hang yourself with.
And this is a problem because?
(It's actually a weak point of Go that you cannot define them in a library without sacrificing type safety.)
Not exactly the same thing, but routine string manipulation in C gets considerably easier once you discover a highly underrated function called asprintf (basically combines sprintf and malloc, calculating the buffer size for you).
But I still need to worry about creating a memory leak with this. :(
But it is infinitely better tasting than Go's ridiculous error handling which is something you would expect in the 1980s.
If your sweet spot is 90~95% java and 5~10% C.
And, what about python programmers, how would Go be for them?
I can't deal with Go. And I don't think it's me--I don't do Haskell because of me, I don't do Go because of it. I find it almost impossible to think in Go. I find it incredibly primitive, well past the point of "stupid code is impossible to misunderstand" and into "stupid code because the language demands it." This wouldn't bother me, in a very "you do you" sense, if I wasn't stuck debugging faddishly-designed tools like Docker and Terraform written in it. To this end I think Go is a regression for the open source community, because what I see as veneration of stump-dumb languages makes it harder, not easier, to be smart about problems.
Since the parent mentioned C and Java. What are you missing in Go compared to Java besides generics? What are you missing in Go compared to C besides manual memory management?
To me, Go seems to have about the same amount of expressiveness as C and Java. The difference being that it's safer than C and more UNIXy/less OO than Java.
To this end I think Go is a regression for the open source community, because what I see as veneration of stump-dumb languages makes it harder, not easier, to be smart about problems.
A lot of open source UNIX software was written in C. To me it seems that if C was acceptable, Go is acceptable (if the application can live with a GC and slightly lower performance). And as the article argues, it lowers the bar for contribution, because it restricts overengineering.
That's a clever way to attempt to constrain the conversation away from the elephant in the room. "Other than the bullet in your stomach, how are you feeling?"
Not having at least Java-style "dumb" generics, in 2015, is unacceptable; the existence of `go generate` should mortify everybody involved with Go. Not having better than that--consider what you can do with Scala even before you get to something like Shapeless--is not quite unacceptable but short-sighted and limiting because suddenly I as a human have to do what a moderately smart compiler can do around type checking and leveraging types to solve problems.
Go's general ignorance, and the community's general ignorance, to really basic functional programming that so hugely improves your life is probably borne out of the stupid type system; things like composition (Try monads) for error handling, so I'm not vomiting `if err != nil` everywhere, things like functional transforms for data structures so I'm not writing for loops until my eyes bleed. And you can't really do that in a statically typed language without either blind casts (which Go partisans recommend, because clearly everything should be `interface {}`, remember the days when java.util.ArrayList just gave you Objects?) or generics.
It's just...dumb, written for the lowest common denominator, and I guess the lowest common denominator is dishearteningly low. Good for them, but having more and more core tools written in this junk makes my job a lot harder because it obfuscates potential problems under a sea of boilerplate and line noise.
> To me, Go seems to have about the same amount of expressiveness as C and Java.
I agree with that assessment. Go's roughly equivalent in expressiveness to Java.
That is a criticism, not a defense.
Go being a somewhat more terse Java 1.4 is not an endorsement of the language or the environment. I stopped using Java quite some time ago because my frustrations with "coding with gloves on" outstripped any benefits of the language. (Not the virtual machine. The JVM is fantastic, I love using it. But Java-the-language is Newspeak: if I can't coherently describe a solution in its syntax and semantics, I have to resort to worse solutions. Go's actually worse for this, surprisingly enough...)
Michael O. Church discusses the problems of Java and the problems if the Java shop very well in one of his articles, and in my experience the Go people I have worked with and talked to almost universally fit into that mold (echoing the normal Java ignorance of the outside world, a neat sense of epistemic closure, and the weird desire to rewrite the world into it).
https://michaelochurch.wordpress.com/2012/04/13/java-shop-po...
> if C was acceptable, Go is acceptable
Should C be acceptable? I don't think so. C is, in 2015 and in truth in 2000, too stupid to live. For a very long time we had no other alternatives, and it is an effective lingua franca because it's dumb enough that you can knock out a language binding in short order, but it's a bad language. No memory safety, no type safety (seriously, just review the rules for implicit pointer casting, you have no types to speak of), and nothing, anywhere, to help you not do things that are damaging.
Like, I'm not a C++ fan because it has many warts and creeping features, but if you literally limit yourself to C with classes, std::string/std::vector, and use pointers only in a last resort (preferring references), you have just solved probably eighty percent of the correctness and security problems caused by our reliance on C. (And you cannot practically implement many of those solutions in C without a level of developer discipline that essentially does not exist in the wild. Just having ctors/dtors is literally transformative to writing safe, smart code.)
Rust will solve more, better, and I'm a huge fan of what they're trying to do, but isn't there yet.
> And as the article argues, it lowers the bar for contribution, because it restricts overengineering.
That's an argument. I'd say that it restricts engineering. Which is not a fatal flaw of a tool, there are lots of problems where grunting and bashing your way through it makes sense, but engineering problems often require being able to actually write what you mean, not write what you need to address the symptoms of the inexpressive language before you get to write what you sort of mean if you squint through the garbage it forces upon you.
Lowering the bar for contribution is only a plus if it doesn't moronize people who are cool with clearing a higher bar. For most of the stuff that I deal with, four novices don't replace one expert. When using Go, I very strongly feel that I can't do my job intelligently because I don't have the tools, and so not only will I do my job more slowly, but I increase the likelihood of doing my job wrong.
For every post like this that has me starting to think "hell yeah, C is really stupid, how can others not see this?" I'm reminded of why Linus Torvalds is glad he didn't choose c++ for git. And... it resonates too bloody well. Especially when I consider all of the ports to other languages that have been attempted for git.
I think it comes down to generalities. The reality is most programs are doing good if they solve one problem. Not just solve it well, but solve it at all. Many algorithms, on the other hand, can be widely adopted.
This leads one to think they could "write with their gloves off" and nail down that algorithm in such a way that it will be usable everywhere. The reality, though, is that it rarely (ever?) works out. What you find is that all of the small corner cases that matter in solving something come back and bite you. Hard.
I agree and disagree with all your points. I have written C++ and Prolog professionally for years, then some Java (because employer), with a little Haskell on the side (hobby projects).
I am in a bind when it comes to PLs. I prefer the abstraction of C++ and Haskell (or Prolog for the domains where it fits). On the other hand, it is easier in powerful languages to get complete mismatches between the level of abstraction and the abstractions that are used. To take three widely-used C++ libraries as an example:
- Boost: highly template and template meta-programming driven.
- Qt: basically C++ as C with classes, with moc for signals. Really only templates for collections.
- Xerces/XQilla: 90ies style C++ with global state, and too many Java SingletonFactoryProxies.
In projects where you use different dependencies with different styles, things can get ugly. Also, your policy-based design may not be understandable to your 'C++ is C with classes' colleagues/contributors.
In the end there will always be interaction between expressiveness and maintainability/accessibility. The right abstractions can improve both. Too much magic (page-long type signatures, too many levels of templated indirection, etc.) can make everyone's lives miserable. The graveyard of ugly C++ libraries shows that finding the right abstractions can be hard, even for experienced programmers.
- `go generate` was never designed as a way to bring generics to Go.
- Most Go programmers are not "ignorant of basic functional programming". They use FP in other languages, and even in Go which has first-class functions, higher-order functions and closures. But it's true that the lack of generics severely limits the usage of FP techniques in Go.
- Go partisans don't "recommend" to stuff everything in interface{} and use "blind" type assertions everywhere. They even recommend the contrary. Give me a link to the Go official documentation that recommends that and I'll revisit my position.
To be clear, just like you, I sometimes miss generics in Go, especially when I'd like to use some FP techniques. But for me, it's just an inconvenience. It sounds like for you it's a showstopper and I understand that. But I don't think that using words like "junk", "stupid" or "dumb" helps in making your point.
I hope, and I'm confident, that the Go team will find a way to add some form or type parametricity that fits well with the overall language.
Unix was designed to port Spacewar. What's that got to do with anything?
> Most Go programmers are not "ignorant of basic functional programming".
That doesn't match my experience. The overwhelming majority of Go people I know, and the loudest advocates to whom I am exposed, seem to regard functional programming as a nothing. Your experience may differ.
> Go partisans don't "recommend" to stuff everything in interface{} and use "blind" type assertions everywhere.
Again, that doesn't match my experience; this was literally recommended to me by a senior-level Google engineer. To his credit, he suggested instead using `go generate` as an alternative. (Because that's better. =/ )
> I don't think that using words like "junk", "stupid" or "dumb" helps in making your point.
Completely fair criticism. But let me put it this way: I view Go, and the terminally blinkered Rob Pike, and his disciples, to be so obviously and monstrously disastrous to what I do for a living that those were the remains after a pretty heavy dose of editing and self-censorship.
I could tell you how I actually feel if you'd like. =)
Don't know about "very", but there would be very little difficulty moving from java to go. There wouldn't be that much value to it though (startup speed and deployment would be the primary ones, and if those are your concern chances are you're not using java as it's notoriously not great at those).
> And, what about python programmers, how would Go be for them?
That seems to be the primary actual market, migrations from python, ruby, php and the like: Go provides a bit of type safety and easy concurrency, an easy deployment story, structural typing is closer to duck-typing than nominal typing (where interfaces must be explicitly opted into by objects) and the fast compilation time means the compilation step isn't much of an issue over "direct" interpretation (/implicit compilation).
I have one more question, how does Go ensure easy concurrency?
Beware though, Go uses shared-memory concurrency (as opposed to, say, Erlang) so if you pass a pointer to a mutable structure through a channel the structure won't be copied or moved, both sides will be able to alter it. It does provide a data race detector but it's just that, you have to hit the corruption path while running the detector for it to have a chance, I'm not sure it's 100% even if you do, and I understand it has a non-trivial runtime cost and limitations wrt number of routines it can track.
Meanwhile, Rob Pike and his contemporaries did language research, particularly related to the semantics of CSP-style concurrency. Syntactically they were all C-like, as the Plan 9/Research Unix community all generally liked it.
Newsqueak was the first and it was a cross between C and with special syntax and semantics for procs (green threads). It was written for GUI workstation environments in mind, the idea being to easily build multi-seat applications. From Newsqueak arose Alef, which refined on it but had manual memory management. Then from Alef came Limbo, the language running on top of the Dis VM that formed the core of the Inferno OS.
Fast forward some years later, Rob Pike and some other Bell Labs vets are at Google. Some event happens which painfully reminds them of mediocrity in computing, that gives them the drive again and they resume right where they left from Limbo.
Go is born.
According to Pike's blog, the real motivating factor for Golang was how forbidding and painful Google's C++ build process was. A lot of Golang makes more sense if you look at it through this lens: above all else, don't be like C++.
You and I disagree in regards to a lot about Golang, but I think you're spot-on here. I've thought for years that it was interesting how yosefk's criticisms of C++ in the "Frequently Questioned Answers" directly correspond to decisions in Golang: "compile times are long" → "use the Plan 9 toolchain", "memory management is difficult and unsafe" → "garbage collection", "templates are a mess" → "no generics", "exceptions interact badly with RAII" → "no traditional exceptions", "header files are a pain" → "use packages and forbid circular dependencies", etc.
I never though to evaluate Golang against it. Great point.
Note that I don't think banning exceptions is really the answer; in particular, the destructor issue is just a specific case of "handling errors during finalization is really hard", and you can't get away from finalization in general. Exceptions really put those issues front and center, though.
Yes, that was the "spark" that motivated it, as I hinted it.
A lot of Golang makes more sense if you look at it through this lens: above all else, don't be like C++.
"Don't be like C++" is pretty much a side effect behind much of the Bell Labs and Research Unix philosophy that values composable byte stream interfaces and liberally using a small number of abstractions.
The historical context behind Go that I wrote about is quite undeniable, though. I feel that you're being a tad too contrarian here, but I'd love to know more from your viewpoint.
Having native CSP gives Golang a differentiator that it would not so clearly have without it. People can disagree about toolchain quality, and for every person that appreciates a well designed stdlib, there are 3 that appreciate CPAN more. It's harder to disagree with a facility that few mainstream languages provide in any form. So CSP is very important to Golang's identity.
It's just not the "why" of Golang (or at least, I don't think it is.)
See this excerpt from the Alef reference manual [1]:
chan(Mesg) keyboard, mouse;
Mesg m;
alt {
case m = <-keyboard:
/* Process keyboard event */
break;
case m = <-mouse:
/* Process mouse event */
break;
}
Now where the toolchain is concerned, again that was adapted from the Plan 9 compiler collection (which even OpenBSD at one point was considering but backed off due to licensing) which makes cross-compilation a surprising breeze.Carefully designed standard library? Plan 9's syscall interface...
Composable APIs defined by one key abstraction? Plan 9 syscalls again, though there it was 9P.
Speed was a motivator, but again - direct side effect of the "5 Principles of Programming" espoused by Rob Pike [2].
Golang feels very much like an offspring of Java and Python to me.
But, even the net package has a noticeable Plan 9 legacy, like the use of dial/listen, as opposed to the clumsy Berkeley socket way. You might recall this was a central complaint of Pike's in his famous presentation "Systems Software Research is Irrelevant".
Obviously it's nowhere near as pure as ndb, but that's the reality of being in Unix.
For me personally Rust is more my style, but I agree with the original author that the structural aspects of Go program construction will benefit large communities greatly. It is something I had not really considered seriously before.
To me when people compare Go to Python, I can't help feeling that means quite an old version of Python (eg 1.5) in terms of expressivity and higher level features.
Python 1.5 was quite a small straight forward language compared to today. Which seems like the goals Go has.
So we're likely headed to where the commensurate Go analogy to Java is a hammer that looks and works like a catheter or something?
One last analogy. What would you prefer: a pilot who has been certified to fly that aircraft and has a minimum number of flight hours or giving every passenger a joystick sticking out of their seat tray so that maybe collectively they won't crash the plane?
Oh, and you kids get off my lawn (waves cane)! ;)
Eventually C will be squeezed into an Assembly like niche, used only for shaving out ms out of an application, kernel stuff or those little code tricks not exposed on the safe layer.
Go is an OK language for server-side stuff. It's not perfect. The concurrency isn't as airtight as its proponents originally claimed. Reflection and type "interface{}" tend to be needed too often. Other than that, there are few killer problems with the language when doing server-side stuff.
The libraries for doing web server type stuff are available and well debugged. When you use a Go library that came from Google, you're probably using code that's executing a few million times a second on Google servers. (As I mentioned on here a few months back, I recently ported a medium-sized production Python program from Python 2 to Python 3. I found library bugs which would have been found long ago were the code heavily used.)
So yes, Go is doomed to succeed. That's not a bad thing.
As for Rust, while I like Rust personally, it may be too complex. The borrow checker concept is brilliant, and a huge advance in understanding how to avoid a big class of bugs. We'll see that again in future languages. The type and generic system, though, pick up where C++ left off, and seem to lead library developers to develop very complex interfaces.
Rust is for people who debate language semantics on Lambda the Ultimate and program in Haskell for fun. Go is for people who have a job to do.
Do you write tools for a woollens manufacturer?
Which is why Java gets used instead.
And given that the JVM is so dominant in big data (e.g. Spark, Storm), online betting and applications like high frequency trading you could make the reasonable assumption that Java is anything but slow.
Go, for all it's short comings and missing features, is closer to the "instant gratification" state that Python and it's ilk enjoy while having performance closer to that of Java.
I'm not trying to say one language is better or worse than the other though. Just my observations as to why Go is gaining popularity.
Like with most things, it really depends on what problems you're specifically trying to solve.
Most people I've seen, that are frustrated with go, are people who want to have an impact on the community by writing a package that a) solves a simple-ish problem with the simplest API possible (e.g. "password-hashing libraries") or b) solves a complicated-ish problem in the most general way possible (e.g. "generic containers" or "graph algorithms"). As go makes both of these very hard, these kinds of people get frustrated with it.
go generally agrees with people who want to solve complicated specific problems, e.g. "I want to find all dead links on a website", because it gives you a relatively straight way from A to B.
I remember reading an article a while back by someone explaining exactly that very well, but I can't seem to find it…
If Go was only used by it's sponsoring company and a few "language-whores" on non-critical systems, then I might have agreed with you. But in spite of Go being one of the "new kids on the block", there are already quite a few sizeable projects and organisations outside of Google who are using Go for fundamental parts of their software stack (eg Cloudflare, Canonical and Docker).
So like or loathe the language, I'd argue that it's already reached critical mass.
What about the people who program in Haskell for work?
> Go is for people who have a job to do.
People use Go for fun.
Without generics and traits, for example, there would literally be no reason for Servo to exist, because it would be too slow. Performance is not optional. Safety is not optional. They are my job. If I opposed language features that are needed for competitive performance or safety on the grounds of complexity, I would be failing to do my job.
I'm responsible for a lot of Rust's features. I have never posted on LTU, and I've never written more than 50 lines of Haskell. I find most of the Rust community's philosophical language debates tiring and pointless; languages to me are tools, not philosophies. The entire core team is largely with me here. I think you have a deep misunderstanding of the language design if you believe Rust has features "just because".
Note that this can have a cost in binary size as generic functions and types have to be instantiated to their actual generic parameters (that can be optimised somewhat when the parameters themselves are dynamic, IIRC while .Net uses reified generics Microsoft's implementation uses a single instantiation for all reference types)
Don't get me wrong. No one doubts the usefullness of generics (not even the core authors of go. Not even Rob Pike as the biggest advocate against generics in go). Just the necessity. And in this specific case, claimed performance improvements.
There are two ways to work around not having generics: use virtual dispatch/reflection (what you usually do in Go, with interfaces) or code duplication.
Virtual dispatch is a non-starter from a performance point of view, not only because of the virtual call but also because of the heap allocation that's usually required to use it. Reflection is even worse.
Manual code duplication makes it extremely annoying to write well-performing code and reduces productivity. Even worse, though, it reduces safety: lots of the generics in Rust use unsafe code under the hood. If you had to manually duplicate all the code, then the amount of unsafe code would explode. (Imagine having to write atomic reference counting from scratch for each and every type that's atomically reference counted!)
As for automatic code duplication via a code generator, that is what generics are. It's just that generics are a particularly good implementation of code duplication: they're integrated with the type system so that the compiler will automatically generate the appropriate code for you without having to go through the trouble of using a separate tool. Having to use a separate tool buys you nothing, as everyone has to learn the tool to write performance-sensitive code, and having to manually request generic instantiations instead of having the compiler do it is a huge nuisance, one that would push people toward not using generics at all and going to virtual dispatch—which brings us back to the performance problems.
The communication issue is, that you seem to equate "generics" with how generics are implemented in rust. I don't see it that way. To me, generics are a language feature, that has multiple possible implementations, one is specialized code generation, as in rust. I think Russ Cox summarises this better than me [0].
And from that point of view, I was surprised to hear, that people thought they would improve performance. Because in my mind, they probably improve terseness and maybe improve productivity, but not performance, if you can write a generic algorithm as a template and do a search-and-replace for pretty much the same compiled result. I think, these difference in viewpoints was, what made this discussion so more lengthy than need be.
And it's important to note (I think) that no one in the world ever doubted the usefullness, of having generics as a language feature (instead of a standalone tool). When gophers say, that rust is overloaden with features, they don't mean useless features, they just mean, that there are a lot of features. Every feature in C++ is usefull. Every feature in python is usefull. But there are just so many of them, which creates a lot of cognitive overhead and always creates the impulse to contemplate "what's the most elegant way to express this", instead of just expressing it and going on to more important things (Mind you, I don't say this is a philosophy that needs to be shared by everyone, but it's the one people have, when they complain about the number of language features in e.g. rust). I think, Gustavo Niemeyer puts this very well [1].
Anyway, I hope you now understand my question better and also understand better, what the philosophy behind go's minimalism is and what people mean, when they complain about too many features :)
[0] http://research.swtch.com/generic [1] http://blog.labix.org/2012/06/26/less-is-more-and-is-not-alw...
> you seem to equate "generics" with how generics are
> implemented in rust
Given that your question was specific to Servo, and given that Rust is largely motivated by Servo, it should come as no surprise that pcwalton's response was specific to the implementation of generics that makes the most sense for use cases like Servo's. > I was surprised to hear, that people thought they
> would improve performance.
Making the compiler aware of generics makes it easier to collapse duplicate implementations, which can have a cascading effect on reducing binary size and thereby reducing icache pressure. > Rust is for people who debate language semantics on
> Lambda the Ultimate and program in Haskell for fun. Go
> is for people who have a job to do.
This is a mischaracterization of Rust to the point of incredulity. I've been talking to companies experimenting with Rust and all the engineers I've spoken to have praised Rust for its ability to let them do their jobs with confidence. These engineers are in domains where GC is intolerable and C++ is considered too much of a risk (in fact, one of my biggest surprises in this current endeavor is discovering how few people in industry will describe themselves as comfortable with C++ to the point of being willing to use it in greenfield projects with confidence). Without Rust, these companies would be forced to buy more hardware to throw hardware at the problem or hire C++ specialists to throw at the problem; fortunately Rust threads the needle and provides extreme business value.Rust was created to solve a specific pain point. It's not some language that sprang fully-formed and perfectly-designed out of the ether. It solves problems that no other language even attempts to solve (no, Ada doesn't do what Rust does (and likewise, Rust doesn't do what Ada does)), and the mechanisms that it uses to do that took years of iteration and concerted effort on large codebases.
Not everyone needs to be working at the level that Rust does, and I think that's great. I'm a polyglot programmer myself, and I like Rust because at last there exists a language that lets me perform at the level of C with the same level of memory correctness that I expect from Python (or really, any language designed post-1995).
Very smooth. /s
Which ones?
Go certainly doesn't succeed because of smug/boring articles like this one. The potshot at Erlang early on (also cf. slurs on Rust and Haskell in some of these comments) betrays the same old "we like it here in our cave" bias of Go boosters whenever confronted with its glaring warts.
Go is a great choice for certain workloads, is reasonably fun to code in, and has great doc support on the web. I suspect however it's popular also because it isn't FP and doesn't favor immutability. It plays well with the haters who refuse to understand how good GC/list fusion/stronger types/better abstraction can make code easier to understand and way faster.
But the bottom line is no Google, no Go. Just like no Sun, no Java. It's simply unbeatable to have a mega tech corp paying folks to write docs libs and patches. But it doesn't save it from being yet another turing tarpit.
Google: Go
Microsoft: C#
Sun/Oracle: Java
almost all others: more on their own merits, from developers eyes (Python, Perl, C++, Ruby, Rust, D, Scala, LUA, JS, etc.)
a language should have innate merits, of course, but never discount the advantages of having a single corporate entity with lots of cash and focus and a built-in install base of eyes
CNRI: Python
AT&T: C++
Unisys: Perl
EPFL: Scala
37signals: Ruby
Mozilla: Rust
Certainly, having a big corporate sponsor doesn't hurt, but it's clearly neither a necessary nor a sufficient condition.
You claim that Go succeeds because Google's behind it. Maybe, maybe not. Then write your own article to make your point.
The paragraph about Erlang was not a "potshot". The author is just pointing out a tradeoff, which is real. There is no question that Erlang is a great language and system.
Potshot. Defend it at your peril.
> All data in messages between Erlang processes is copied, with the exception of refc binaries on the same Erlang node. [1]
But I have to agree with you that the paragraph about Erlang in the article overstates the issue. In most cases, messages should be relatively light and then the copy is not issue. It's an issue only when you need to transfer or share a complex data structure.
If I'm not mistaken, in the current implementation of BEAM, each lightweight process has its own heap and this is the reason why data must be copied. But it could be possible to allocate memory from an arena shared by all processes, and because Erlang data structures are immutable, messages exchanged by processes could contain only references. The cost would be a more complex garbage collector, with the related latency issues.
[1] http://www.erlang.org/doc/efficiency_guide/processes.html
How about we consider the author of the blog post, the Go community, and the Go language's designers in a more charitable light. Perhaps the points made in the article are actually valid: that language features involve tradeoffs, some of which are measured not just in terms of performance, and that languages are designed to achieve certain goals that might not align with yours.
Yes, I imagine that "Go certainly doesn't succeed because of smug/boring articles like this one" although I'd remove "smug/boring." Before I used Go I hated it "from first principles", because I had used Scala and Clojure and Haskell and Reactive Extensions and all sorts of FP goodness. But to make a long story short, once I started using Go I really enjoyed it and now I willingly choose to use it to solve problems. It was the use of Go that convinced me that perhaps these absolutes from FP I believed in weren't quite absolutes after all. But this doesn't mean that I consider Go to be some kind of perfect holy grail of programming, either.
Does that make me a hater who refuses to understand? Does it make me some kind of idiot for regressing from FP? Or perhaps the goals of Go aligned with my team's goals, and that was really helpful and valuable to us?
I characterize Go as having glaring warts. ":=" will bomb on reassignment UNLESS you destructure alongside a new variable. Wart. Try to close over a variable in a loop; wince in pain as you make a throwaway anonymous function to do so. Wart. Don't get me started on "interface {}".
Nonetheless, I think Go is a great tool for the right job. I don't think it's "better for open source" (WTF???). I wouldn't want to write a massively-concurrent (not parallel: concurrent) system in such a loose-goosey, non-polymorphic language. But that's just me, knock yourself out.
Very true.
This article hits the nail on the head. Most people say that they cannot "express" certain things in go, or have to jump through hoops to do it. The point of go is not to create a highly expressive language, but rather to create one that has a high enough abstraction to be productive but simple enough so that people coming from different backgrounds can acquaint themselves with it quickly.
In other words, it is a language for teams.
Not coincidentally, Golang sucks at this problem.
But there is something about writing in Golang that makes it easier to dive into meatier code. For instance: I've written programmable assemblers in Ruby and in Golang. With Ruby, I kept refining the assembler until the DSL looked identical to normal X86 assembly (I even hooked the bracket operators to make them behave like dereferences). With Golang, I quickly moved past the assembler into an IR and a compiler.
That is a great way to compare languages. Incidentally, that's the same way I feel about Scala vs Python.
Same experience here. I am working on a neural net dependency parser and pretty much started C++ and Go implementations in parallel, because this was one of my first larger Go projects and I had my doubts about using Go for this.
In the meanwhile, the Go implementation is a complete and fast parser (the number crunching is done using OpenBLAS via gonum), which I now use for research. In C++ I am still tweaking the abstractions for the basic stuff (word embeddings, transition systems). Of course, I could make a simple, straightforward implementation in C++, but the language encourages you to finetune the abstractions and you have to the choice between template-heavy/light code (with its respective downsides).
I also found that Go encourages me more to break stuff up more in different packages. In C++, every separate library means new build machinery, some way to roll it out on systems, etc. In Go it's as simple as creating a new repository and adding imports.
1. Go channels: send every value over a channel.
2. Callbacks: provide an iteration function which takes a callback function.
3. Closures: let a closure return the next value when called.
4. Iterators: create a separate iterator type with e.g. HasNext()/Next() methods.
In this respect C was much simpler, because only (2) and (4) were really possible (and sometimes indexing).
edit: Okay, 3 should work too, sorry.
>KDE (1996)
>LibreOffice (based on StarOffice, 6.0 released in 2002)
>VLC (2001)
>LLVM (2003)
I think you have a point r.e there being more smaller projects than large projects with large teams. But this is a terrible argument. Go was released in 2007. Are you being facetious or are you suggesting that porting a mature codebase to Go is that easy? CoreOS was released in 2013 and so was Docker. I know that Docker actually ported to Go after the fact, but it was still relatively young and Go was already mature by then.
Also, despite Go's short existence, there are already a surprising number of large Go project (Docker, Syncthing, etcd).
Reminds me of Java. Although, Java gets increasingly complex these days. It also started out without generics.
I really like it.
To me, what's been abundantly clear is that: it's a horrible choice for types of apps a lot of people are using it for. Specifically, systems where ror/django/express/php have traditionally excelled at. I'd say "CRUD", but that's too narrow. The expressiveness and productivity of dynamic languages continues to awe me. This is particularly true for web systems that, on one end, deal with the object-relational mismatch and on the other transforms and outputs json or html.
Go's great, but it feels like we've forgotten some of the pain-driven lessons Hibernate and their ilk taught us.
You essentially need language-level support for dealing with data at your boundaries. Even with Java's strong reflection (Go's reflection is horrible) capabilities and generics (and C# extending that with lambdas and expression trees), there's still tremendous friction and boilerplate configuration and code.
Consider Dependency Injection, an ilk. In most (all?) dynamic languages, DI is a language concern, as opposed to a library concern. By having support for it within the language, the problems DI frameworks attempted to solve in Java (or C#) via messy configurations, legalese-like unit tests and quantities of code dedicated to nothing but the infrastructure of the codebase, simply vanishes. Now people are going to Go and discovering the awesomeness of interfaces.
I've been looking for someone to verbalize this train of thought for a few weeks.
The problem with this idea is that, for the exact same goals, there could be a much better design for the language and much better implementation of various details.
You don't need to be Haskell or anything. Just Go + generics for example would result in a much cleaner language (no special casing for things like "make" for example), a vastly improved code library and data structures story, etc. This horse has of course been beaten to death (including by people working extensively with Go, so it's not like some "outsider's misconception" as some dismiss it).
If Go succeeds is because noone else with the same kind of visibility and resources tried to compete in this space (easy concurrency, static builds, fast compiles, static, fast-ish, decent batteries included etc).
You have e.g. Rust which is incomplete and too complex, Nim which is too niche, from very small vendor (a guy) and has some bizarro ideas, and that's pretty much it. That said, Swift might make a dent in this area when its Open Sourced if it has nice tooling.
Compiler-enforced-correct manual memory management may not be the right choice for every project, of course, but I think "too complex" is too strong of a way to say that. That implies there was a simpler way Rust could have achieved the same goals, and I've never seen anyone suggest one that works.
http://docs.oracle.com/javase/6/docs/jre/api/net/httpserver/...
http://docs.oracle.com/javase/6/docs/jre/api/net/httpserver/...
As for incomplete, I mostly refered to the tooling and the available library ecosystem. Even Go lacks there, and Go is an order of magnitude better there than Rust. That said, despite the recent 1.0, the language is also heavily worked upon in several aspects (internals etc) and it doesn't seem that it's a "complete" offering that just happens to do incremental improvements, but a "we got an 1.0 out of the door, but we've got work to do to make it more mature".
Yes, there is more of a learning curve, but I think that's a problem with manual memory management in general. To me, that doesn't mean that the language is "too complex"; rather it means that the space Rust is playing in (and which those other languages are not playing in) is complex.
> As for incomplete, I mostly refered to the tooling and the available library ecosystem.
I've never found Rust lacking in tooling, with the notable exception of the lack of rustfmt (which is being worked on by Nick Cameron and others). I use native profilers and GDB with Rust almost every day, and Cargo is getting pretty mature. The library ecosystem isn't very mature yet, sure, but I wouldn't say that makes the language incomplete.
This is most likely the why of the incomplete remark of the OP.
The difference is in the learning curve. The concepts Rust forces down your throat are the same ones you'd need to learn in some way in C++ anyway (well, not the same concepts, but similar ones having to do with avoiding segfaults). The difference is that you can write simple programs in C++ whilst blissfully unaware of the perils that come later. On the other hand you sometimes need to understand ownership for even the simplest programs.
But for a larger application, you have the same amount of learning required if you want to responsibly write an app in C++ or in Rust.
When we're talking about using a language for something other than teaching programming newbies, we really don't care about small prime number programs being harder in Rust. We care about how hard it is to write large applications, and I strongly suspect Rust isn't harder than C++ for this.
Oh, by the way, for the most part lifetimes work themselves out[1] without effort from your side. And if you find them complicated, you can always compose the relevant wrapper object (like Rc for refcounted memory management -- almost a GC) and use it. It's a bit more verbose, but it's not hard to grok.
[1]: http://manishearth.github.io/blog/2015/05/03/where-rust-real...
Except you have to solve those very same problems on your own with every other type of resource that is not called "memory" in other languages.
Ownership is a huge problem, having built in primitives to handle it is a benefit. Having or not having GC is almost (but not quite!) a separate discussion.
Yes, that's probably the case (Rust caters to more complex needs). Still makes it more difficult to just "dive into it" like you can with Go or Java or Python etc. Of course it's probably much simpler compared to mastering C++ or getting C right without dangerous bugs.
- last time I checked there was no option to have non-blocking IO which is a pain.
- custom JSON serialization/deserialization from/into custom data structures is extremely painful (for reference, rustc_serialize's Decodable trait).
- thread::scoped leaking destructors under certain conditions. This is more of an example of how a complex language gives rise to complex issues that very are difficult to debug and fix.
This will get better in time obviously but this is the current state of the language. Nonblocking IO in particular is really unfortunate to see in a 1.0 version tag.
Regarding thread::scoped, I think that kind of issue isn't unique to Rust (Java, a language with a simpler memory model, has had all kinds of weird corner case bugs, especially around memory and concurrency). It's also, again, more an issue of "safe manual memory management is hard": the simple ways to avoid that issue would have been "GC everything", "sacrifice memory safety", or "remove reference counted smart pointers", which contradict Rust's goals.
Can you point something in particular?
Note that this problem is one that has no analogue in other languages.
In most languages, including Rust, you can already "leak" things by putting them into a static hashmap and forgetting about it or sending them to a blocked thread or whatever.
Rust is unique in that it can demarcate types which are bound to a scope. Which gives the auxiliary guarantee that the object would be destroyed in that scope regardless of what happens next (because such objects cannot be returned from the scope or placed into a global hashmap or whatever). There is no analogue for this in other languages. Rust is not "incomplete" for not having this.
The current scoped API depended on this guarantee, but it turns out that there are convoluted ways to bypass the guarantee (so it's not a real guarantee). There's a new design that's been proposed which doesn't need this guarantee.
non-blocking io can be done via mio, and I think using serde for json is easier.
I think http://arewewebyet.com/ speaks to the completeness point sufficiently. Rust-the-language is probably complete enough for all but the most serious use-cases, but Rust-the-ecosystem isn't.
Twenty-two days after release, Rust started talking about making breaking changes (https://internals.rust-lang.org/t/pre-rfc-adjust-default-obj...). This conversation killed a Rust project I had pushed for... it played into all the existing negative ideas about Rust (constantly changing, not worth investing in) and gave the doubters all the ammo they needed to kill the project.
The change wasn't yet implemented, and had ZERO impact on our code-base even if implemented. But Rust-the-community seems too clueless on the importance of APPEARING stable and able to follow promises.
I wonder how many other Rust projects died because Rust-the-community appears like an untrustworthy ally (I am speaking of perception not reality).
It's untenable to guarantee that, in a strict sense, the universe of all possible programs that run on 1.0 will always have the exact same behavior on 1.1. With any language, there are plenty of ways to break code in theory on upgrades that are very unlikely to lead to problems in practice; as an obvious example, incorrect unsafe code that depends on undefined behavior can break when the compiler starts optimizing based on that undefined behavior. I think that, instead, what we can realistically guarantee is that code that actually compiles in 1.0 compiles in 1.1. If there's no code out there that actually breaks, then I don't see any problem.
Golang has made many changes that could technically, and actually did, break code as well (just to name a recent example, the GOMAXPROCS default bump; there have been several others).
Exactly, which was my point. Rust-the-community (and you as a member of it) see no problem with it... which for me, IS the problem. The timing, the fact that it played into all the existing narratives about why you never trust Rust, it made it a brutal bit of political weaponry in the hands of those who are pushing against Rust in organizations... and a bit of a kick in the junk to those of us who supported it. You saw it as without impact, when it has already had a huge impact on at least one organization.
> Golang has made many changes that could technically, and actually did, break code as well (just to name a recent example, the GOMAXPROCS default bump; there have been several others).
Rust isn't Go, that might seem "unfair" but that is the way it is. Go does not have the same reputation to fight against as Rust, the same famed history of breaking peoples code who are trying to use it, Rust WILL be held to a higher standard when it comes to breakage than ANY other language I suspect.
Tell me what you wanted Rust to do instead. Again, the options seem to me to be either "make potentially-breaking changes silently without gathering feedback" or "make no changes to Rust that could break any code ever". If the latter, realize that this implies we could never add functions to modules (because of glob imports and shadowing), we could never add modules, we could never add trait implementations (because of method resolution), we could never add to the prelude, we could never upgrade LLVM (because of undefined behavior), and probably a whole host of other things I'm forgetting.
> Go does not have the same reputation to fight against as Rust, the same famed history of breaking peoples code who are trying to use it, Rust WILL be held to a higher standard when it comes to breakage than ANY other language I suspect.
I'm not sorry for doing so much development in the open instead of behind closed doors, even if everyone got to see how much the language changed from 0.1 to 1.0 and it acquired a reputation of "changes all the time". The point is, it doesn't change all the time now. From 0.6 to 0.7, for example, all code everywhere broke. Same with 0.7 to 0.8, 0.8 to 0.9, and 0.9 to 0.10 (though the amount of breakage got less over time, as you would expect). Conversely, the amount of breakage between 1.0 and 1.2 (assuming the trait lifetime change goes through) is so minuscule we don't even know of a single crate anywhere in existence that it would break. This is, in my view, so different as to be incomparable.
Well -- if we are going into what I would have preferred. I would have preferred a rest period after release. No ongoing changes across 3 trains on a 6 week cycle. Give the community time to accept, adapt, bitch, moan, whine, create workarounds, and then better workarounds. Let enterprises have time to buy in, test, accept or reject and give feedback. Deal with critical issues and focus on stability as a deliverable... and don't break anything during the rest period (even if that means being on a single version of LLVM and no new traits or modules or functions or whatever). But, that ship has sailed.
> I'm not sorry for doing so much development in the open instead of behind closed doors
Who asked you to be? I was simply pointing out the reality that Rust has a reputation to contend with -- you can't change that be being righteous about it, it just is.
The arrival of the 1.0 release also doesn't imply that the language is "done" or ready to use for anyone's particular use case (e.g. Servo is still on nightly, and will be for the foreseeable future). There are crucially important things that are currently being stabilized, and delaying those for an additional three release cycles would just be an arbitrary obstacle for those seeking to shift their code from nightly to stable.
We also don't need three release cycles to get feedback because we've been collecting feedback all throughout the 1.0-alpha and 1.0-beta cycles. Now would be the worst time to institute a freeze on API additions because of all the APIs that people are clamoring for but that didn't make it to stable for 1.0 (https://github.com/rust-lang/rust/issues/24028).
We're also working closely with several dozen companies using Rust to determine what development to prioritize (if you would like to add your company to this list, then please see the email address in my HN profile). As a result of this collaboration I expect to submit an RFC next week to propose that Rust 1.5 become the first LTS release, with subsequent LTS releases happening every at every fifth release. Do note that this idea is very preliminary (don't take it as gospel), but if accepted it would mean that we have until October 30 to stabilize any features that we want corporate users to be able to take advantage until the next LTS.
(As for that proposed "breaking change" that 1) wouldn't break any code in the wild, 2) would be trivially fixable with a lifetime annotation, and 3) could be opted out of with a single attribute, every company that I have asked about it has said that we should go through with it.)
Sadly, in the near term, the Rust boat has sailed. LTS releases would give a real good reason to reconsider if they ever come about. What support durations are you considering for LTS, and where can I read more?
Sure generic's would be nice, but I do not feel they really would change much. After using and supporting Go for years, I would rather keep it how it is. Simple and verbose.
Getting up at 3am in the morning to respond to a page going off in a production system that you didn't write, there is something extremely parseable with Go. It doesn't hide and abstract things in a way where you have to end up digging.
Often the docs are just not enough to really understand software. In the event you end up having to go read the code to understand it, when things get that far, I wish it was Go every time. There is little in the world more frustrating than having to read 18 java files to understand a simple format of a payload because your coming in late to the codebase.
It seems that you can't really make the claim that adding generics leads to a "much cleaner language".
This trivializes all critique to "to each his own".
That some people "want different things" doesn't mean all things people want are equally valid.
[1]: Java Flight Recorder is the most powerful low-overhead profiler I've ever seen.
[2]: We use Java, Kotlin and Clojure all in the same project.
[3]: The ability to inject ad-hoc tracing code into your server and then take it out -- all while the server is running at full speed -- or to shadow binary dependencies so they don't clash, or to use (or write) a time-travelling debugger is like having magic powers. Bytecode manipulation is ultimate hackability.
It's true that Go doesn't have a lot of those powerful JVM features that you listed, but as with any engineering trade-off there are lots of people who judge the benefits of Go to be worth the loss of those things.
You'll also note that since that article was published, all the advantages listed in in it have either found their way into Java (lambdas, fibers) or to other similar languages like Kotlin (multiple return values). Go has the undisputed upper hand when it comes to command-line apps (I really like it that I can use a language so similar to Java for stuff I never liked using Java for, and I was never fond of using scripting languages that require tedious dependency management for standalone programs), but is at a fundamental disadvantage when it comes to long-running important servers.
No, it has more GC issues. It's just that there aren't yet enough libraries and big applications to make that apparent. It hasn't been stressed enough just yet.
(I'm not saying this is a negative for Java, BTW; making shared memory data structures both fast and idiomatic is really important if you care about performance of parallel code.)
Only because most developers don't care to look for the JVMs that offer AOT or refuse to use anything other than the OpenJDK.
However, for me, Java was the first language to get ditched when I got comfortable enough with Go to accomplish similar tasks.
Reasons are many, but Go definitely wins "single native binary" argument. Java has to be installed, and it has different versions that can be installed. Go you simply compile for whatever platform you want, and you literally have a single native binary. No other dependencies need to be installed.
Hot code loading and swapping is neat in Java, but most places I have worked do not have the operational skill to really take advantage of this, and instead compound that against the JVM's slow startup time, which makes it double bad. With Go, you ship a simple binary that starts up very quickly, and so operationally the effect of faster, more seamless deploys are a much better experience.
For me personally, those aren't a big of enough of a win. I would rather have simple code that is fast to scale and fast to understand.
Dealing with something like a thundering herd of traffic is much more difficult when your application can take upwards of an entire minute to start up, and to optimize itself to run at decent speeds.
There is likely a sweet spot however. My good experiences with go are working on high scale projects with a handful of other senior level developers. Some other projects I am involved in are with more enterprise shops with many more developers with a wider array of skill levels. In projects like these the other aspects of JVM like how well supported it is and how there is so many other tools for it, it might still win in one of these enterprise environments.
But for many of my use cases, the JVM just feels like it has everything-and-the-kitchen-sink, and sometimes you just want a small, nimble solution that does a few things well.
1. Go's over-fitting to Google's development style, especially the over-reliance on dependencies as source-code.
2. Go's lack of hackability that might bite you down the line when you need something that Go really can't provide. Go's only hack-hook is source-code manipulation (which brings us back to point #1), and at this early a stage we already see too many tools going down that ugly road.
Go is probably the least hackable mainstream language I've encountered. In C/C++ you can always poke around the implementation details when there's no other choice; with Rust there's unsafe; with Java (and other JVM languages) there's full bytecode control; with scripting languages there's metaprogramming. All those "backdoors" should, of course, be used sparingly if not rarely, and then are best done by experts and hidden from sight, but they're always there for when you need them -- and you invariably do for that last 1%.
With Go -- there's absolutely nothing. You can't even drop down to C to muck about because you'll mess up the delicate runtime. So Go is indeed a descendant of C, Java and Python, but neglects to provide the hackable escape hatches from the plain language semantics all of them do.
Those two things scare me (not that I'd give up on deep monitoring or polyglotism otherwise, but still) because not only are they risky, they're exactly the kind of thing that people don't notice when the project is young. I feel like there's a very important lesson here that seriously bit people in the ass that Go failed to learn (well, that and no support for immutability of any kind).
Least hackable is a hard thing to define, but as you've defined it I suppose I agree, albeit in this context it often comes across as a feature to me.
Monkey patches are always monkey patches, and in golang your forced to fork a library to modify how it works. To me this is a good thing. It means that as the codebase evolves, the amount of "hacks" (if you will) are more often than not more clearly defined, and to maintain these hacks its easier to collaborate back and make a pull request, rather than just build up a collection of hacks that have to be maintained separately.
The fact that there is a higher barrier to entry to make these kind of changes, is simply not always a bad thing. Choose your poison, I guess. Golang is all about trade offs. In this case the trade off is its harder to simply add arbitrary code all over the place, but in exchange the culture of golang is more simple.
The only one that actually seems decent is the metaprogramming, which, in my experience, tends to lead to overcomplicated code and worse performance.
All in all, the only times I've ever needed an escape hatch is when I've been writing hacky things, or trying to be too clever. Too much "clever" is bad when programming.
Why are they brittle? They're not brittle at all, they just have looser semantics than the core language. They have their own semantics, which the runtime guarantees to uphold.
> that binary will always run the same... If you aren't testing your code before deployment, that's your fault.
Why work in such a primitive way? We're very familiar with what happens when source-code is overly dependent on a specific compiler version. Besides, dropping to C/assembly in a language with such a high-level runtime (not only a GC but its own global scheduler) is not an escape hatch; it's just using power tools to break through a hatch-free thick wall, which might work if you're careful not to break the foundations by mistake. You could do the same in all languages that do provide an escape hatch, too (if you'd rather break through the wall instead of using the hatch).
> Too much "clever" is bad when programming.
Absolutely, but sometimes just the right amount of clever can let you do truly powerful things that would otherwise be beyond the reach of the language. It's there just for those moments when you're stumped[1].
Experience (and I've been doing this for twenty years) shows that this point where some cleverness is necessary, always arrives at some point in the project's lifetime, and that cleverness often saves you a whole ton of work. Remember, the average codebase lifetime is about 10 years.
[1]: Plus some truly powerful stuff, like the ability to inject tracing code into a running application and then take it out.
That's not true. All JVM libraries expose a ton of monitoring information through the standard JMX interface at every level of the stack, from deep inside the JVM, through logging framework, DB drivers, schedulers etc., and all the way through the application.
And I can only guess that you've yet to encounter Go's even worse GC problems with large heaps.
> Java unfortunately has a mountain of legacy cruft which makes it a pretty terrible choice for new hires to ramp up on.
True, but only in legacy codebases. A new Java project is as pristine as a new Go project, and new Java libraries are just as lean (because there's a lot of cross-influence between the two environments).
The problem is that most Java developers have become so familiar with and attached to bloated frameworks that they simply aren't interested in trying any other way. They have a lot of time and effort invested into mastering these frameworks. "Let's use Spring for that", and endless talk of the "persistence layer" for even the most basic apps.
You're implying that the mere switch -- all things being equal -- has an inherent advantage, while I say the opposite: all things being equal, switching languages is always a net loss, other than a possible advantage in recruiting in some regions where HN is popular. Of course, all things are never equal, so there are many other considerations.
http://newsgroups.derkeiler.com/Archive/Comp/comp.lang.schem...
Google is a resume tick box. Go over to AngelList and look at lists of startups. Take a drink every time you see 'worked at Google' listed as a qualification. You'll be destroyed in an hour or so.
Thus people get jobs at Google, put in a year or two, and go off for a higher paying and/or sexier job or a startup of their own.
Go is laser focused on simplicity, maintainable code bases, and uniformity to allow the next crop of Valley recruits to pick up where the last crop left off.
Like every programming language ever, there are surely many Golang users who've used it solely to add a keyword to their resume. That's not a very interesting observation, because the same thing is true of Rust, Scala, and even Haskell.
Further, that doesn't really address the question of why so many teams select Golang in the first place. A programmer might use Golang to get the keyword on their resume, but a team shipping a new product has no such incentive.
It's quite similar to the notion of "I'm a PHP developer and I don't understand why everyone says it is terribly designed! I learned to work with it and never tried anything else, so it can't be that bad!!!".
Not every developer cares about software development. There are plenty of people who chose this profession after they heard that a random developer can become the next Bill Gates by writing the right iOS app.
Having a language which doesn't require an inexperienced and non-interested developer to reflect on all the lessons learned in the last 40 years of software development and computer science fits the bill of this kind of person pretty well.
Sure, he/she is missing out on 4 decades of improvements to this profession, but who cares? Despite all the medical advances, there is still an economic niche for quacks selling "cosmic crystals" to cure your cancer.
There is nothing wrong with this. People don't pick a job in finance, because "they like to work with numbers" either.
We should just be aware of it.
So, "not knowing any better" is kind of ridiculous.
(For many jobs one year of experience is perfectly fine!)
I think people who can think critically and evaluate various options rarely join personality cults, which kind of explains Go's current community.
I largely dislike Go but keep picking it because it is the lowest common denominator of languages my team will use and I really like them.
Even the proponents of Go on my team are moving away from it as their preferred choice, but for now it remains the only consensus fallback.
The next language I want to learn is OCaml, but thats because I'm sort of obsessed with unikernels.
GO fits the bill.
It's true that many abstractions pay for themselves many times over, but not all do. For some applications, this means that a language encouraging a more direct solution comes out ahead; for others one looks for languages that make the wanted abstractions cheaper.
I think this premise could not be more wrong. The open source community is not a project team, and open source project teams are very likely much more homogenous and stable than teams working on commercial software.
Yes there may be non core contributors, but if contributions are not up to standard, they are simply rejected. If that means slower progress an open source project can live with that. A commercial project can not, because it has deadlines.
Looking at github, the lines of code are usually easy to understand in C and java. What's difficult is how the parts of the project fit together (which is never documented). Does Go help with that?
[ Design patterns were supposed to help with this, with recognizable groups of classes. Sounds like a good idea, but I haven't found that, but maybe I don't know them well enough, or projects don't them well enough. ]
For reference, I have used OCaml, Haskell, Golang and C extensively. I think Golang is a wasted opportunity to replace C. It's a mediocre language with a bunch of annoyances.
Could you elaborate on what you mean here? Why do you not consider Go a language? What do you consider the requirements to be a programming language?
I don't think either is true. What I do think is true is that every language makes trade offs and golang makes me less productive with it's choices & restrictions. I'm reserving judgement about how it impacts my teams aggregate productivity.
You install the JVM once and rarely upgrade it.
You build and distribute your Java apps as fat jars (meaning, all dependencies bundled.)
This is a solved problem.
We're looking at Go right now, and our instrumentation is currently done manually at the source level. Are there, or will there be, tools to add instrumentation similar to those available on the JVM? I'm sure it's possible...
You'll also find some people who say the opposite. We need to qualify what kind of simple we are talking about? Are we talking purely about language?
Are we talking about standard libraries? Ease of use of API's? Ease of use in analyzing performance?
If we just compare Go's syntax to Haskell's syntax you'll find they both have few reserved words.
The former can seem, snide or condescending, even when that is 100% not the intent.
I write both C++ and C# frequently. I love both languages. But I deal with people who use either language exclusively and continually gripe about the other. And the proper response is, "it's probably just not the right tool for the thing you're trying to do."
The promise of stability from a large software corp puts in place a solid language foundation people can rely on when building apps in the language. Someone building a successful app using the language shouldn't be able to dictate future changes to the language based on their own needs only, ignoring smaller or less popular apps. Golang's language spec is a big help with this.
When you've tried working with a language whose backers cancel work on a spec for 10 years, then tailor the language's functionality for the one application they themselves are building, you appreciate the promise of stability. When the language's backers open up their AST to programmer addons via annotations, then later duplicate the functionality of the most popular addon, you appreciate the backing company's understanding that long term benefits come from nurturing the community.
When you see a backing company suddenly retrench all the staff working on a programming language, you appreciate that Google is using Golang internally and is unlikely to do the same. Although Golang was born of a Google internal need, let's hope the needs of their own systems won't dictate future changes at the expense of the external community, and that they keep their stability promise.
What a brilliant sentence.
This would almost be right, but Go has much poorer language interop than C due to the GC and non-C compatible ABI. This means unless we're going to a monoculture of GoAllTheThings (not likely), Go will never succeed C as being the basis of fundamental open source community projects.
For myself, I was and remain mildly interested in Go as my next move off of Python(2). And still believe Go is a better move than porting to Python3- which as an aside makes no sense technically, but the coercion/threats from the Python3istas are beyond reproach (as if the existing Python2 community is the problem), and set me solidly against it. Of this new generation of languages, Swift was always my ideal. Both in language and implementation. Now that it's going to the server I can't help but find the attraction of serverside Swift and getting in on the groundfloor of that ecosystem. While gaining skills in the language of iOS to be irresistible.
Count me in as one eager for Swift 2.0. I believe Swift is the language that is doomed to succeed. http://www.tiobe.com/index.php/content/paperinfo/tpci/index....
With it also being open source, and ported to other platforms I can imagine other mobile operating systems also embracing the language in hopes to get more developer traction.
Not to mention that they have taken a little from every language, and server-side swift is a whole different beast.
This is going to be fun ;)
I hate how languages like Go get lumped in with "Google", an association which to me, is negative. For many, people fawn over Google, thinking a for-profit like Google does things in their best interests. When in reality it's temporarily mutually aligned interests.
I'm at the core if anything, a Mozilla guy. Not entirely because I'm not too diehard on the JSAllTheThings movement. I strongly lean towards native, even if my work consists mostly of Python2 backend for webapps. At least with native executing code it's possible to be open source. You never know what's executing serverside. So I'm less of a fan of the so-called "open web" (an oxymoron) than most. And that's discounting the difference in end product that exists between native/web. I like my web to be it's original intended usecase- such as how HN is. Nothing too fancy, data sharing.
I think from a language/implementation standpoint that Swift hit it on the money. That's what I would have wanted out of a Python3. If that were Swift, I'd be a huge fan. Swift just nailed what I believe people are really looking for. Go is a little sketchy in ways. I don't hate it, don't actively work against it as I do Python3... well, can't say I work against it but I don't extoll its technical churn. But Go at least is trying to solve a real problem, and solves more problems than it creates. Even if I think it squares up against Java more than it does C or Python.
Unfortunately, Swift is associated with Apple which has its own zealots (and zealous haters). It's regretful that programming is now fashion, hype, trend. But I do think they have the best-of-breed language here for general purpose use.
My money and personal contributions to these new wave of languages will definitely be to work on server-side Swift solutions. The thought of a single-language solution with a single GOOD language from backend to front if you use iOS is pretty amazing and I'm really looking forward to that, and Swift backend / web frontend as well.
Go was designed to create low-level stuff with high-level language and it does not need features beyond that. It has enough features to satisfy some extreme low level tasks. If you want high-level programs then write them in your favourite scripting language. I prefer coffescript due to its expressiveness but I realise that t is not everyone's cup of tee.
However, for low-level programming and where I know static compilation and performance is a key, I will go with go. Why? Because it will take me 10 times longer to do it in C. And although I like C, I will not kill myself to use it unless I am really have to.
P.S. my company has done some amazing stuff with go, docker, fleet and coreos in a very short time. I have no doubt it would have taken us much more time if we had decided to use something else.
The best Go code uses built-in types and small interfaces in its APIs. Use interface{} as a last resort, and then only if your function can really take anything. Don't overuse channels. Sometimes a mutex is more appropriate, and that's ok. Rarely use reflect. Don't panic except during package init. Never ignore errors. Don't try to make your Go code conform to the way other languages work. Magic is bad, don't try to make your code magical.
The go community is quite nice in general (there are bad apples in any group). Show off your code, it's the only way to learn, and chances are you'll get some good review comments at least.
(1) where does Rust fit in this?
(2) and if Go is lacking in the concurrency department and loses to Erlang in latency. Why don't people use Erlang/Elixir for servers and Python/etc for client side?
It doesn't. Not any more than other languages anyway.
Because Erlang is different. It's not just the syntax, even though that throws many people uncomfortable with much that's not a direct descendant of C syntax; it's the whole programming model which requires a real shift in perspective that simply isn't easy.
It's worth it once you start to "get it", but that can take a bit.
I do think Elixir gives the Erlang VM a better shot at the big time, because it lessens the syntax obstacle for many people.
I'd say that fails to capture the full scope of the statement.
From where I stand, Erlang is not just a language - it's an extremely robust, highly opinionated event loop with its very own DSL.
It's very reductive. Erlang is a distributed platform with a functional programming language, lightweight processes communicating through distributed asynchronous shared-nothing message passing, preemptive scheduler, etc.
> Go won’t let you abstract yourself in the foot.
aside from being amusing -- I like this, but can anyone confirm its true in practice with Go?That said, I'll just leave this here: http://yager.io/programming/go.html
The simple type system and lack of genetics makes code verbose. The dependency system seems to require everyone is on the bleeding edge, correct me if I'm wrong. The channel based concurrency is very elegant but appears to be too coarse grained for high performance programs that would otherwise use it.
That said I like the languages simplicity and do think it has it's uses in the world. Just not large team, large project development.
Now this language is actually used for large applications. It's still all gravy, the code bases are still uniform and easy to understand. People can easily be trained. More projects adopt this language, or even use it to build things from scratch. It gets applied to more domains. Years pass, and things that were unobservable in the beginning start to rear its head. They weren't non-existing, but they were so minuscule in this large landscape (remember - big adoption of this language) that it was unobservable from the bigger picture. Now what was a problem for a few developers seems to be a problem for many people. For a while, they solve this pain point by educating about certain patterns to look out for and solve. This works for a while, but after a while more pain points become apparent. And like for the initial pain point, it is just not a pain point for a small group of ignorable developers, but indeed a systemic one. There seems to be something wrong. We can't simply solve this pain point with education and applying patterns - we need abstractions. There is some murmur about this - the principal point about this language was to avoid over-abstracting things. We need to practice constraint. This works for a while, but after some time the concerned voices of the people advocating this kind of restraint gets drowned out. These limitations are just too much for people to deal with. So people start suggesting and inventing so-called abstractions. And pain points are relieved. After a while you have a whole cottage industry of these abstractions. And people's day to day life with this language and its associated code bases are happier and more productive. On the other hand, there is more to learn now, and things aren't straightforward any more. You can't simply look up a library and have flat, easy to read code. You also need to learn the associated abstractions. You also notice that the technologies associated with these abstractions are getting kind of big. They are starting to take on a life of their own. And it seems like they don't really fit. Some of them feel kind of shoe-horned in, as if there was no general slot for them already installed, it just had to be jammed in there.
Now, is this language good for large-scale development? The language is still easy to learn. Somehow. There was a bunch of additions up through the years to ease some pain points. Not all of jive as well with each other, or with the original language. But with some elbow grease, it is perfectly serviceable. Not to mention all the associated technology that cropped up to assist the language in its ascent - that is the hard part. So the language is not really easy to learn any more, with the associated things. But people know it, there are code bases to maintain and it has proven that it isn't useless.
Is the language good for large-scale development? Doesn't matter. It already won and is here to stay.