5 ms·
I've never been a Go evangelist. For years, the appeal and praise lavished upon Go flummoxed me. Until I decided to use Go for my latest product. Then it made s
by Denzel 11y ago
I've never been a Go evangelist. For years, the appeal and praise lavished upon Go flummoxed me. Until I decided to use Go for my latest product. Then it made sense. For most purposes Go is "good enough." And it's good enough in enough areas for me to set Go as the standard, de facto language at my company, unless there's a damn good reason to use another language.
I appreciate Go because it's fast, small (re: syntax and standard library), garbage collected with nice primitives (pointers and slices), concurrent with high-level primitives (goroutines, channels, select), expressive enough (strings, maps, range, first-class functions, type system, etc.), first-class support for Unicode, and it has a rock-solid standard library.
About a month ago, I started learning Go. It's so small. The language, the standard library, the tools. They're all so easily digestible; it took me 4 days to work through the Go playground, read the entire Go specification, work through and learn 40% of the standard library, and start writing production-ready programs. C was the last language that enjoyed a language/standard library this small, to me.
The same thing can't be said for Ruby or PHP, or any other languages I've worked with. In almost every project I've been involved with, there would be usage of some arcane corner of the language. Whether it's determining the byte offset of a member function in C++, or the GCC extensions to structure initialization in C, or metaprogramming magic in Ruby. All these cracks and crevices are difficult to keep in your head. This isn't so with Go. It's easy to keep the entire language and standard library in your head; providing a certain ease and flow when building a program.
Ease of use applies to memory management as well. Go offers just enough control over memory to make it pleasant to implement and use real data structures. Try implementing an LRU cache in Ruby/Python that evicts based upon an object-size policy without wasting a ton of memory simply maintaining a linked list. When I built a distributed real-time, type-ahead service in Ruby I was fighting the language the whole way when it came to simple data structures, memory management, and concurrency. (It was just a prototype, I know Ruby wasn't the right tool.) Originally, I was going to rebuild the service in C++, but that would've taken too much time. Instead, I opted for Go and it was much easier, and obviously much more performant. Not as performant as an equivalent C++ service, but performant enough.
I don't think much needs to be said about Go's concurrency. First-class primitives such as goroutines, channels, and selects along with solid standard library support in sync and sync/atomic, makes for a powerful combination. Go wraps these concepts in a very bland, mainstream way. Making them more accessible to more people with little time investment.
You're right, Go will not win based upon the # of LOC written. However, after writing 20k+ LOC in Go over the past month, I don't see any reason to write any of our back-end code (infrastructure, services, web servers, tcp servers, etc.) in anything other than Go. It's good enough in enough areas to make it much faster for a team to standardize on just this one language. Not only does this reduce the time wasted due to context switching between languages in a polyglot shop, it makes it a ton easier for anyone to jump in and contribute anywhere at anytime.
---
To give my thoughts some context, here's a subset of my professional and personal language/project history:
- Ruby: 100k+ LOC Rails monstrosities and smaller 20k LOC projects
- PHP: 200k+ LOC bare-PHP e-commerce websites and 50k LOC CodeIgniter/Laravel intranet apps
- Python: 10-20k LOC utility and server management scripts
- C++: 500k+ LOC open-source 3D game engine and multiple <10k LOC personal projects
- JavaScript: ~35k+ LOC for the front-end work on some websites I've worked on
- Common Lisp: read all of Practical Common Lisp and ANSI Common Lisp, and dabbled in a few small programs
- nickbauman 11y agoFair enough. I'm reminded of Hickey's talk on the difference between "simple" and "easy". I just did a CLOC on the latest golang github repo: its now at 1,000,000 LOC. The Clojure repo (which is considerably older)? 40,000. Talk to me in a few years when you tire of this.
- danburkert 11y agoThat's not exactly fair. Go implements a runtime, GC, etc. all of which Clojure inherits from the JVM or the JS implementation.
- nickbauman 11y agoThat's a "trueism". However, the CLOC was on the Go part of the repo. Go's GC isn't implemented in GO.
- masklinn 11y agoIsn't the runtime implemented in Go since 1.5? A quick overview of the C content[0] shows that the C source in Go is mostly cgo (either test cases or the runtime integration[0]) and the shootout C sources (for bench tests?). [0] https://github.com/golang/go/tree/master/src/runtime/cgo https://github.com/golang/go/tree/master/src/runtime/cgo
- lmm 11y agoWell I'm not surprised you can't see any reason to write anything other than Go when you've never used a language with a decent type system! If you're ever standardizing the language for a whole team I hope you'll take the time to evaluate a decently typed language first - OCaml or Haskell or F# or Scala (or I guess Rust if you absolutely need to avoid GC)
- Denzel 11y agoI wish I had the time to evaluate everything that is out there but I don't. There's simply more important things to focus on for my company than choice of language: sales, hiring, fundraising, etc. Therefore, I had to choose the best option for me with the limited information I had at the time. But that doesn't mean I can't be convinced to adopt another language. :) If someone ever surfaces a highly persuasive point-by-point argument for OCaml or Haskell or F# or Scala that applies to what we're doing, then I'll reconsider. So far, I haven't seen such an argument.