Why Go?
nathany.com
nathany.com
This is certainly not the case for the way that I personally think about C. Perhaps there are two "spirits" of C; two ways that people think about it:
1. C is small, C is simple, C lets you write useful programs with good performance while keeping the language itself simple. For this view of C, I can see Go being a compelling alternative.
2. C is a bare-metal environment for implementing low-level systems code like VMs, garbage collectors, JITs, and other runtimes. It imposes nothing and never gets in your way. For this view of C (which is how I think of it), Go is not an alternative. If you are inclined to disagree, answer for me: why is the Go runtime and GC not itself written in Go?
I think that perhaps the difference between these two views of C leads to some of the disagreement about whether Go is an alternative for C.
In a word: bootstrapping.
It's a FAQ: http://golang.org/doc/faq#What_compiler_technology_is_used_t...
I wouldn't be surprised if it's doable with some really clever tricks, but it doesn't seem worth it in terms of maintainability. Just use C or C++.
Or does Rust's optional GC get in the way? I'm not really familiar with that part of the language.
(The compiler currently makes heavy use of `unsafe`, in my understanding. At least for now.)
https://github.com/mozilla/rust/issues/3608
Writing the Go runtime in Go would require the similar ability to do without all the services that are currently provided by the runtime. That is, unless you want your runtime to recursively require itself to infinite depth. :) I'm sure it's theoretically possible, but considering that two of the language's largest selling points are concurrency and memory safety via GC, a theoretical runtime-less dialect of Go would be so near to C that it might not really be worth the effort.
Edit: Forgot to mention that it does not do escape analysis.
Are there actually popular GC implementations that don't use any assembly?
go's void* http://golang.org/pkg/unsafe/#Pointer
go's syscall mmap function. (Pure Go) https://code.google.com/p/go/source/browse/src/pkg/syscall/z...
pure go pkg with more mmap functionality. http://godoc.org/launchpad.net/gommap
Go's runtime mmap function. (C) https://code.google.com/p/go/source/browse/src/pkg/runtime/s...
Go's base memory allocation function. https://code.google.com/p/go/source/browse/src/pkg/runtime/m...
Go functions body may be implemented as asm. The standard math pkg is a great example of this feature. http://golang.org/src/pkg/math/
Considering all of these features there isnt really a whole lot about Go's semantics that prohibit it from being used in many of the low level projects that are typically written in C/C++.
"Some of the facets of the spirit of C can be summarized in phrases like:
• Trust the programmer.
• Don’t prevent the programmer from doing what needs to be done.
• Keep the language small and simple.
• Provide only one way to do an operation.
• Make it fast, even if it is not guaranteed to be portable. "
The same unsafe constructs can cause memory corruption in the verification tool and lead to a behavior where the wrong decisions are taken.
So the fact that many C verification tools are written in C itself does not proof anything about how safe the language could be.
For me personally C could be much better if:
- There was no automatic decay from arrays into pointers (call an explicit operation to do so, like &a[0])
- There was a proper string type available
- Arrays were bound checked (with optional disabling of bound checking, like many other languages offer)
It turns out that an uncompromising devotion to clarity is quite powerful in its own right. It's not right for every use case, but highly compelling for many.
I think some of us already had that with the first Java versions. Actually, Go looks a lot like old Java versions, minus the VM, plus Goroutines/channels, and static duck typing.
I have written a fair share of Go code and ultimately it's a very boring, but predictable language. If it builds a larger ecosystem, it will not be much different than a Java that compiles to native code. Without some of the advantages of the JVM.
(What we are really seeing here on HN lately is a hype, pretty much like node.js and FP before. Go has a better chance to stick, because it has a good steward.)
But also performance. JVM can be faster than say C/C++ code in many cases.
Snapshot and release builds of our build server are distributed via a Nexus-managed repository. So, everyone codes against exactly the same dependencies, regardless of the platform.
- Hotswapping/JRebel.
- Good interoperability with other languages. E.g. the Typesafe folks implemented Akka in Scala. Java gets it for (well, almost) free.
- Easy monitoring and instrumentation.
Obviously, there are downsides as well, such as startup times (twofold: starting the VM and Hotspot detection/compilation), preset heap size, expensive JNI (native interface), etc.
Well, so Go is "write once, build 3-9x, run anywhere".. close enough ;)
But Java bytecode execution is definitely not slow and usually within 2x the execution time of a C implementation, which is faster than the vast majority of other language implementations.
[1] At least in the language benchmarks game. Yes, I know that microbenchmarks are not representative, etc. etc. etc. (Until your favorite language is faster ;).)
A community that's converged on a deterministic, crossplatform way of representing library dependencies (maven).
An ABI that includes a notion of objects, which makes cross-language interoperability with objects easier (though counterbalanced by not having a cross-language notion of functions).
But I'm actually a bit cynical about that. Pretty soon the framework peddlers will descend on Go just as they have descended on Java, JavaScript and Python. Once again a couple of switch statements will be replaced by tens of thousands of lines of framework code.
It will be called "beautiful" and "elegant" and "DRY" and those still complaining about the bloat will be told that they don't have to use the features they don't need, but not knowing all the features and all the hooks and all the optimization tricks will once again make you look incompetent and behind the times.
Play, Grails and Vert.x have shaken up web development. Scala, Groovy and Clojure for languages.
But I don't agree with the prediction: Python and JavaScript aren't really drowning in BS produced by architecture astronauts. It exists but it's not prevalent.
True, and we already have that for those willing to pay for Java native compilers.
Even when you add types, it's still an amazingly simple model. And the types do not generally affect the runtime behavior of code at all.
Functional languages are the very picture of something simple but not necessarily easy. Go, at least for you, is the opposite: it's easy because it's similar to what you're used to, but it also has quite a bit of surface area.
My impression is that Go vies for simplicity of implementation over simplicity of semantics. It is a very operational sort of language. Its goal is to make the how clear--the code reflects what it does.
Languages like Haskell, on the other hand, are completely the opposite. Haskell values simplicity of semantics over simplicity of implementation. It is a very denotational sort of language. Its goal is to make the what clear--the code reflects what it means.
It's a difference in philosophies, certainly, just not quite in the way you construed it to be.
Exceedingly simple semantics combining to form a difficult-to-use language is often called a "Turing Tar Pit," a place where everything is possible but nothing of interest is easy.
Conway's Game of Life is even simpler than the lambda calculus, and people build all sorts of amazing things in it, but examples like a calculator that outputs human-readable digits are circus tricks.
Who was suggesting that we should form difficult to use languages on those simple semantics?
Very good for replaceable programmers, the dream of every manager. :)
You mean its strength is that is a Blub language?
Because the "low cognitive overhead" is exactly what Java was touted for, back in the day (before the EE madness).
I can see both sides of the "clever is better/worse" argument, though. E.g. - C++ operator overloading is powerful and harmful.
- Horrible build systems (and horrible build times)
--- Go compiles fast, and the compile and dependency system is baked in
- Impossible to untangle dependencies (don't ever remove an include, who knows where it is used)
--- Go forces you to either use a dependency or remove it, stopping dependency cruft from ever building up
- Nightmare deploys (system wide assumptions)
--- Go deploys with a single platform dependent binary, it is absolutely awesome
- Inconsistent formatting, self-directed standards on formatting.
--- Gofmt is the one true format, heck, even some bad formatting won't compile (try to uncuddle your else to see)
- Inconsistent build systems and build system quality, made worse by using libraries and systems that have their OWN build systems.
--- Go get combined with its include system (use it or lose it) really let you tie together systems in a sane way without any custom build routes.
- Dealing with modern concurrency
--- Go having built in channel communication makes many problems trivial, and allows new methods of abstraction (goes to Go's model of composition).
- Horrible build systems (and horrible build times)
Maven is a great build system, Java has good compile times, and most modern Java IDEs have incremental compilation. And you can specify versions of dependencies, rather than having to maintain a list of SHA1 hashes of versions considered to be stable.
(don't ever remove an include, who knows where it is used)
This is primarily a problem in C/C++, where one can indirectly get the correct dependencies by accident. Most modern compiled languages don't have this problem.
Go forces you to either use a dependency or remove it, stopping dependency cruft from ever building up
Which can be annoying for debugging. I'd rather have my IDE or linter give warnings.
- Nightmare deploys (system wide assumptions)
'mvn package', it's also easy to configure maven to build an archive with dependencies, configuration files, or whatever you'd like to be in a deploy.
In fact, deployments are even easier than in Go, since my package built on OS X will also deploy on a Linux server. My colleagues use different platforms (a mixture of Linux, Windows, and OS X) and it's never a problem.
- Inconsistent formatting, self-directed standards on formatting.
It's good that the Go team made a standard formatting. That said, my employer has a default layout. It's a matter of importing an XML file in Eclipse or IntelliJ and everything is in company layout (yay).
- Inconsistent build systems and build system quality
Nearly every Java library is available via Central Maven Repository. Including versioning :), meaning that if upstream changes their API, it's not your problem. In contrast to Go repository/packages.
Dealing with modern concurrency
Ever heard of Actor models and Akka? Composable concurrency, across more than one machine. With supervision, routing, etc.
Or you could use Go and the text editor of your choice.
brew install maven
And use the text editor of your choice.(Or you could just install IntelliJ and get a stellar development environment with nearly everything you'd ever need.)
Yes, functional programming is based on the idea that abstractions should be cryptic. That's a very reasonable observation, and not at all ignorant.
Well, it included closures, so luckily it's trivial to add those after the fact.
Maybe trivial, but not lots of fun.
But I admit, fast startup times and coroutines are big wins.
Also, multicore is late. Dual-core x86 in 2004, and in 2013 we are still on quad-core. With a doubling every two years, we'd be at 32 cores. Instead, today's trend is toward the less powerful ARM. We do have "multicore" in GPUs (1000's). I've long thought that processor evolution will be similar to organs in a body or firms in a market-place, i.e. with special-purpose silicon, like video decoders etc. Which is what we have with SoC.
Heck, even a dirt cheap Dell 1U with 2x X5670 has 24 threads going.
Server loads are typically embarrassingly parallelizable, e.g. serving concurrent web requests. I mean, consider, are you maxing out all 8 cores? Multicore utilisation is hard, in general. So desktop cpus pretty much stalled at quad-core (I expect ARM chips are doing likewise as we speak).
Looking at the details, I don't think general concurrency is a solved problem. Looking at the results, if it was, we'd have much better utilisation of multi-core architectures by now than we do. For example, 32 core x86, clocked ultra-low, for extraordinarily low power consumption.
Actually, another issue is that message passing might work better with cores with their own RAM, so the modules can work independently.
I think there's a huge amount of kool-aid around concurrency "solutions" - functional programming, erlang, and now Go. Because concurrency is so valuable, if Go really does make it trivial, we it should quickly dominate all other languages. But it seems to me that concurrency is still a hard problem.
It is out there, a lot, used in trading houses, used in running credit reports, used for facebook chat, used to route cell phone calls, used as the back-end component to gobs of system (CouchDB, RIAK).
Erlang has a very similar culture background to Go, it wasn't built for Academia, it was built to solve issues right in front of its creators, real world problems they struggle with everyday, inside Google and Erickson respectively.
Both are un-sexy, get-er-done type languages. Erlang has found happy homes all over the place, and I have no doubt Go will do at least as well -- most likely far better.
Previously I have also done GUI programming with Python, and the freedom from: not worrying about indentation, slow speed and default sync behavior is relieving.
Talking about verbosity is a bit dodgy since it also depends on the skills of the programmer. But, at-least in my case, I think my Go code is less verbose then I would have written in Python. One of the main reasons for that is the highly accessible type system.
I can't imagine a more concise syntax for automatic delegation than Go's embedding.
Can you write any program in Go that cannot be written in less lines (often half) in Python?
That's not necessarily a good thing. Those '20 years of cruft' represent battle-hardened code. Those features have been requested - maybe not by you, but communities the size of Ruby, PHP, Python don't do these things on a whim.
The feature linked is Ruby refinements, for which much of the community was against. And note, I did not say refinements weren't wanted, clearly they were wanted by someone. I said they aren't needed.
Outside of those cases, Rob Pike has given some discussion on interior pointers and how it's possible to limit the amount of garbage generated: http://talks.golang.org/2012/splash.article#TOC_14. (along with the usual techniques, like object pools, used with good success in JavaScript and Android games).
"Ultimately, though, it sounds like you want a language which has no garbage collection, and Go is not that language. Language constructs will allocate memory in ways that are not immediately obvious, so there is no reasonable way for a Go program to completely manage its own memory."
https://groups.google.com/d/msg/golang-nuts/LoJJ1bICduA/AQFt...
Of course you can write memory pools and free lists—you can write them in any language—but, like other languages, the GC will still trace them during mark time and there is no safety provided by the language if you return an object to the pool that's still in use, or leak objects by forgetting to reuse them, and so on.
The fact is that programming in Go, for all practical purposes, requires using a garbage collector.
And with JRebel, Play or Grails you have no startup time anyway. You just hot swap the code in the JVM.
...and it's perfectly useful for small things.
...and not really useful for serious web applications.
As the article points out, there's no real web framework for go, so the majority of things (web apps that is) written in it are toys (see http://go-lang.cat-v.org/go-code).
Most pointedly, there's no compelling structured database story, just a mess. The no-sql solutions like mgo are as good as it gets really. ActiveRecord / SqlAlchemy / NHibernate runs rings around anything that currently exists, and without it, your traditional web apps are pretty difficult to build. You'll find a lot of commentary along those lines from people who've tried.
(...but it turns out a lot of people want tiny little web servers that don't do very much, and serve json. It's great for that~)
Not true at all. As I covered in the "Go 1.1 released" thread[1], there is no "de-facto" web framework, but there are a handful of good ones: web.go, beego & Revel, to start. Think Flask, Sinatra & Django, respectively, in terms of complexity/kitchen sink.
You are right that there is no "great" ORM in the vein of SQLAlchemy/ActiveRecord, but that's partly because: a) the language is young, and b) the language attracts people that don't like the generalisations/performance issues associated with ORMs.
> ...your traditional web apps are pretty difficult to build.
What's a "traditional web app"? A CRUD app in an MVC style? Sure, you won't be able to turn something "big" around in a short amount of time like you can with Django/Rails, but difficult on the opposite end of the spectrum. You can certainly turn around something performant and scalable, and it's unlikely that you will have to strip components out to keep things fast.
You can, however, bolt together a handful of packages (again, see [1]) and go down the Flask-style route, which seems to be becoming more and more popular these days as people eschew the growing complexity of the bigger frameworks.
Except that's not what I said.
Go can be used for big things on the web. Google uses it for dl.google.com; SoundCloud uses it; amongst many others.
What I am saying is that there isn't a defacto "kitchen sink" framework for Go, but this does not stop large applications from being built.
The same tools for small sites scale nicely to large ones in Go.
There's a reason for that.
(and absolutely, yes, for things that don't it's a totally viable solution)
Uriel is dead. So don't link to cat-v.org as if it was an up-to-date resource.
I know you can cluster Java servlet containers, but those apps tend to too often be initially architected as the "one true immortal process", stuffed full of long lived session data.
https://github.com/danenania/go-promocodes
It's a tiny rest api for generating promo codes to bypass in app purchase locks in an ios app. It uses gorilla/mux[1] for routing, mongodb with mgo[2], and is heroku-ready[3]. One file and 129 lines all told.
Perhaps it can help.
1: http://www.gorillatoolkit.org/pkg/mux
3: http://mmcgrana.github.io/2012/09/getting-started-with-go-on...
Please don't say this.
If you are being paid by someone else, please check with them to ensure what their priorities are when things "scale big" bc often times you can bide yourself time if you have their requirements met while you scramble to make everything perfect on the backend.
If you are not being paid by someone else or this is a side project, then please do not try and solve this question now. Answers to questions of "scale" are so broad that you will drive yourself mad trying to find the "perfect" tool, when one doesn't exist. You don't scale a language or a framework, you scale application logic. Scaling to millions of requests is the best possible problem to have, but put yourself in a position to have that problem!
And asking basic questions of how to build something that can handle some amount of load in a language that you are not familiar with will FAR outweigh the perceived benefits of choosing that language/framework!
Building an API in Go feels -very- robust because of the strong typing and the strict compiler. After a while you'll discover the strength of interfaces and be pleasantly surprised. Combined with the performance boost, I can't think of a better language to write an API in.
Reasons: 1) the implementation is not vulnerable to path traversal attacks (i.e. if url.Path == "/../../../../../etc/passwd"). 2) It automatically handles index.html 3) It uses "/etc/mime.types" and other system files to automatically set mime types 4) It streams the file back instead of reading it all into memory.
I'm developing my new startup (http://www.TurboHDR.com) in Go on App Engine and it's a very nice development environment.
As part of the process I recently developed a WebDAV package (which I'll open source soon) and it was quite straightforward thanks to Go's great XML package (http://golang.org/pkg/encoding/xml/) which automatically unmarshals XML into regular (possibly annotated) Go structures. The JSON package (http://golang.org/pkg/encoding/json/) can do the same. It's the most painless experience dealing with XML I've ever had.
As another example, here's a simple (and admittedly, pretty frivolous) web server I wrote in Go to generate random passwords: https://github.com/jbarham/random-password-please.
Please do! Sooner rather than later -- no need for perfection ;)
https://github.com/sauerbraten/crudapi
You could also use it to implement CRUD parts of your API and define your own handlers for more complex API parts.
I'm looking for cool Go projects out there, so share your github stuff!
See previous discussion(s):
Because sometimes I like just smashing the "leading" values into a structure, rather than having to write a constructor (or worse, NOT writing a constructor and having to set, set, set my "bean" to make it useful)
It's almost as much fun as TurboP^H^H^H^H^H^H ANSI C.
The funnier thing will be when the hype disappear as fast as it came.