The generator given as an example in the official blog [0] is called "stringer". It is made of 639 lines [1] mixing ast parsing/traversing and printf statements. If this is what I am supposed to write then of course copy-pasting becomes a pragmatic alternative.
[0] https://blog.golang.org/generate
[1] https://raw.githubusercontent.com/golang/tools/master/cmd/st...
Not saying that it's pretty, but it's quick and easy.
It reminds me of this: http://typicalprogrammer.com/abject-oriented/
I can understand that instantiating templates by hand is not so bad. But once it is written, maintaining the code is not so obvious for someone not acquainted with it.
Did I introduce a bug or not in the code? Not easy to tell without context.
Is it mildly annoying to type out those three lines? Sure. You know what's a lot more annoying? Basically everything else in programming.
When you dive into a codebase full of vaguely similar yet different blocks, it starts being more than mildly annoying to understand the intent of the code and make the correct change.
type userList []*User
func (u userList) Len() int { return len(u) }
func (u userList) Swap(i, j int) { u[i], u[j] = u[j], u[i] }
func (u userList) Less(i, j int) bool { return u[i].Name() < u[j].Name() }
What change would you ever need to make to this code that would be at all difficult? The first two methods on userList are never ever ever going to change. The only thing you could possibly want to change is how to sort inside the Less method... and that code would be the exact same code you'd have to change no matter what language you're in. You still have to define the sort one way or another for non-trivial types.So, yes, it's some extra typing... but saying that it makes maintenance harder is just plain wrong.
And more seriously, there are times when factoring out "common" code makes the code significantly more complicated, and often turns your common code into a morass of special cases as your application progresses, and these cases that looked "the same" end up being "not quite the same".
https://play.golang.org/p/Ya7tUhDnO2
*edited a typo
I feel a little sorry for you because I put a trap for the parent poster in the original code.
I wrote "a[j] < a[i]".
You "fixed" it while refactoring, which would be the good thing to do if I made a typo. If however I really wanted to sort circles differently from planets, then you made an error while refactoring what looked like copy-pasta but wasn't.
My original point was that when you "have" to copy-paste, you cannot clearly see what is or isn't part of the copy and what is new.
You found a way to rewrite the code without much copy- pasting, and I am happy to see that. Still, in other places where code duplication arise, there could be similar problems from a maintenance point of view.
fixing level selection again
commit dae018e4f76db0e9da810b4560d6c8e1c7029048
Date: Mon Apr 11 07:06:47 2016 -0700 fixing level selection for hint case
commit a754bcd0d09ab1e357ae28c8f06baf65d879878f
Date: Sat Apr 9 02:33:14 2016 -0700 forgot to fix the level selection in the move caseIf I could actually reuse code properly I'd only have to fix it once.
Without effective code reuse, I have to hunt down the copies, each of which may have slight modifications to make them better fit their use case (and might be hard to grep for as a result), figure out whether or not the bug exists in that copy (and whether it can actually be triggered), and fix it there.
The description of inheritance in http://typicalprogrammer.com/abject-oriented/ seems relevant here. (Edit: Derp, junke got there way before me!)
JVM is a major drawback for any language. Many people don't even look at JVM languages.
A Go for the JVM would immediately give Go developers much better optimising compilers, high quality cross platform IDE-integrated debugging and profiling, much stronger garbage collectors, ability to access the large quantity of Java libraries that are out there, ability to mix in other non-Java languages too (javascript, ruby, R ...), code hotswap, better monitoring tools, a vastly larger standard library, better code synthesis tools and so on.
The JVM is hardly a liability. It adds features and carries a cost, but Go is substantially similar to Java in many ways and getting closer with time. I do not see any credible plan from the Go developers to beat the JVM developers in terms of GC or compiler quality, for instance.
In my experience Java brings a mindset that there must be some complex way to solving a problem so lets find out that.
By optimising for a single metric whilst ignoring all other criteria, Go's GC is setting its users up for problems. Just searching Google for [go 1.6 gc] shows the second result is about a company that can't upgrade past Go 1.4 because newer versions have way worse GC throughput: https://github.com/golang/go/issues/14161
Their recommended solution is, "give the Go app a lot more memory". Well, now they're back in the realm of GC tuning and trading off memory to increase throughput. Which is exactly what the JVM does (you can make the JVM use much less memory for any given app if you're willing to trade it off against CPU time, but if you have free RAM then by default the JVM will use it to go faster).
BTW the point of an optimising compiler is to make code run faster, not reduce memory usage. Go seems to impose something like a 3x overhead vs C, at least, that was the perf hit from converting the Go compiler itself from C to Go (which I read was done using some sort of transpiler?). The usual observed overheads of Java vs C are 0 to 0.5x overhead. The difference is presumably what the compilers can do. Go's compiler wasn't even using SSA form until recently, so it's likely missing a lot of advanced optimisations.
tl;dr - I have seen no evidence that the Go developers have any unique insight or solutions to the question of building managed language runtimes. They don't seem to be fundamentally smarter or better than the JVM or .NET teams. That's why I think eventually Go users will want to migrate, because those other teams have been doing it a lot longer than the Go guys have.
Yes. HotSpot has had configurable max pause times for years and years [1]. If you want less than 10ms, set MaxGCPauseMillis to 10ms. It also has a state-of-the-art generational GC, which is very important for throughput, as bump allocation in the nursery is essentially impossible to beat with a traditional malloc implementation.
[1]: https://docs.oracle.com/cd/E40972_01/doc.70/e40973/cnf_jvmgc...
> The following example JVM settings are recommended for most production engine tier servers: -server -Xms24G -Xmx24G -XX:PermSize=512m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:ParallelGCThreads=20 -XX:ConcGCThreads=5 -XX:InitiatingHeapOccupancyPercent=70
So Oracle mentions 200ms for most prod use. I am not sure how you are able to deduct ~10ms pause from that link.
And just because one can configure ~10ms does not mean at JVM will start respecting it. There is nothing in any official document by Oracle about max GC pause time. The results Google threw are mostly around ~150ms as min pause.
> It also has a state-of-the-art generational GC.
And it needs something like
http://www.amazon.com/Java-Performance-Charlie-Hunt/dp/01371...
to do what JVM can do in theory. In practice as a java users I am used to seeing ~20-30 sec pauses for Full GC.
The only effort in open for sub 10ms GC for large heaps is Project Shenandoah:
http://openjdk.java.net/jeps/189
and it is long way from availability.
Nongenerational GC pretty much always without exception loses to generational in heavily GC'd languages like Java and Go. There is no silver bullet for GC; it requires lots of hard engineering work, and HotSpot is way ahead.
There's always going to be edge cases in any GC/compiler/etc ... you just can't account for every case. I suppose with java's infinite knobs, you might be able to... but then you have to tune the GC. In Go, there's just one knob (a slider, really, more CPU vs. more RAM), and 98% of the time you'll never need to touch it. I had honestly forgotten it exists, and I work on a large Go project daily at work.
People can and for big servers often do, to squeeze out more performance or better latency, but it is definitely not required.
In the presentation I linked to, GC tuning (after switching to G1) reduced tail latencies a bit, but otherwise did not radically change anything.
Can you build a language that runs on the JVM that compiles as fast as Go? Perhaps. Java sure ain't it, though.
You can use the 'javapackager' tool in Java 8 to make a tarball that contains a JRE. It's not small, but that's a result of the age of the platform; it just has a lot of features (in Java 9 there is a tool that can make a bundled but stripped and optimised package).
Go binaries are getting larger and the compiler is getting slower over time, as they add features. They don't have any magical solution for bloat: eventually, they'll add the ability to break the runtime out into a dynamic library as it gets fatter and fatter.
Or of course they can just refuse to add features and doom their users to a mediocre, frustrating experience forever.