I've run Go in production for a web application, and I'll say that Go is not a great choice for this task. The built in HTTP server doesn't have a way to shut down gracefully, there's not a good zero-downtime restart story, and the standard library SQL package (and abstractions on top of it) has some nasty warts that only show up under concurrent load.
If you build a webapp in Go, be prepared to spend a lot of time monkeying around with problems that are solved issues on most other platforms.
That does look pretty gross, thanks for sharing. Any other ones stick out in your mind? I've been happy using Go against postgres, but haven't had a significant enough load to run into real problems yet.
There are a few bumps and warts. The server close issue was one that made wonder if they ever tested, but I eventually discovered you can close down a server:
One of the first things you're likely to desire after going through this tutorial is more sophisticated routing, the gorilla toolkit has an excellent reversible routing system that works with the std lib http packages:
You can actually read the go language spec in a couple hours. You can pick up and be productive in the language in a weekend. And yet you can optimize code down to the byte level where needed. This is the uniqueness of Go. It is familiar enough that most anyone can look at some code and figure out what it's doing, but it's not hard to make complex and performant code. Simple and powerful is better than complex and powerful.
> And yet you can optimize code down to the byte level where needed.
I can't see how this can be true in any real form if I can't completely turn off garbage collection. There's a lower bound to your ability to eke out additional perf when you have to take into account a stop-the-world garbage collector that you don't directly control.
I'm certainly not the best programmer around, but I tend to subscribe to the notion that perhaps complex and powerful exists because that complexity grants additional flexibility to those who know how to use it. (Hell, Rob Pike has admitted as much on his blog regarding why Go doesn't appeal to many people who are competent C++ programmers. Though he decided to frame it as if it's a negative, which I really appreciated.)
Go makes it easy (and common) enough to avoid spurious allocations and to reuse memory. The GC is often relied on about as much as explicit deallocation in C++, not as much as in functional or dynamic languages.
Question for Gophers.
How do you guys debug your code? What IDE do you use?
Scala works beautifully with IDEA IDE, one of the best IDE out there! GUI debugger just works out of the box.
I tried using Go for a little bit but I find IDE and tooling support for Go is a bit lacking. Do people consider these aspects anymore when they evaluate a new language? A proper IDE support can greatly boost your productivity!
I debug it using Printfs as needed--it just doesn't need a ton of debugging, and Go makes it easy with the %#v format in Printf giving an appropriate, annotated representation of pretty much any data type. Stack traces are also very informative if something goes badly wrong.
I'm pretty sure GDB works now too, but again I have never really felt the need for it. But then, I've never really felt the need for syntax highlighting, code folding, or auto-completed function names. I feel like if my Go code has reached a level of complexity where it needs those things, I've done something wrong. My IDE is Acme, it lets me edit files, run my build scripts, and execute test programs.
This sounds like me when I was still in college trying to hack out a 100 line of code for a small programming assignment... But this approach does not scale with a million line of code project. Anyone with real programming experience can tell you this. Corporates don't just shell out thousand of dollars for an IDE license for no reason. :)
Crap, there I was thinking developing Go for my employers was "real programming"! I guess I should go add a lot more boilerplate and un-needed complexity, maybe rewrite it in a true enterprise language like Java. Then it would be a big enough project to need an IDE, making it a "real" project.
Maybe I should just delete all these repos I've worked on for my job, the cluster management tool, the pedestrian simulator, the GSM radio emulator, the VM monitoring infrastructure, the distributed key-value store. They were written in Go, so I guess they weren't real programs.
You can always use gdb to debug. However, with type safety and proper unit tests (which are easy to write with Go's interfaces) you often don't need it.
Ad-hoc debug output does scale to large projects. I have not used an interactive debugger in about ten years.
My style is to only log when I'm debugging a failure I don't understand. Then I remove the log output.
I also make sure that my unit tests cover the problem case I was debugging, because problems that require this kind of detailed debugging tend to be the trickiest to keep maintained without regressions. And I try to make my code based on careful state management (or, if possible, statelessness), preferably with a state machine.
I've been programming for over ten years and the only situation under which I need a debugger is when I'm working with a language that allows segmentation faults.
Maybe debuggers are useful to you in other scenarios, but they are by no means necessary. You don't need to be inflammatory about it.
In Go I do poor man's debugging, print statements. Knowing the exact line number of an error is most of what I want for debugging. On errors Go shows the stack with line numbers. An IDE might be icing on the cake but there are usually disadvantages to be accepted as well.
I'm building something, one aspect of which can be considered as a Go IDE. So that's what I use. It'd be pretty hard for me to go back to just ST2 and a terminal for writing Go code now, but it's not quite ready for mass usage yet. I'm working on it as fast as I can.
Have a blog or some kind of "sneak peek"? I must admit I'm very much in love with the combo of ST2 with the free GoSublime plugin, Goding is a breeze with it...
Sure, take a look at https://github.com/shurcooL/Conception - there are some screenshots in the README and if you're feeling adventurous, you can compile the thing on OS X or Linux out of the box. There are also some older public-oriented binaries in the simple-live-editor branch.
There's still a lot to do, and much of that is stuck in my head at this time, but I'll do my best to put it all with the source soon. Plus I gotta work on "presenting" it a bit better (in a way that is more friendly towards other people seeing its long-term value and getting them interested in collaborating).
I've often wondered about using Go as an architectural choice - it's near-native fast, the syntax and semantics are good, it's GC'ed and runs on Linux (edit: my language of choice is C# - and Go is the only one that comes close to it _and_ runs on Linux, IMO - any others out there?- performance is critical).
However, if I decide to go with Go as a framework choice, is there an active market of Go developers out there from which one can hire?
I've spent the past couple of months working with Go, coming from a mostly C# and Python background. One of the attractions to the language for me is that it's straightforward to pick up. Because there aren't a lot of "fancy" features in the language like Linq or list comprehensions, it's easy to dive into a block of code and figure out what's going on without requiring a lot of background knowledge.
The language eschews some brevity in exchange for clarity, which gives me a lot of confidence that I can take a good developer from any background, give them a week and feel like they've got a decent chance of acquiring the knowledge they need to work with the language.
The newness of the language means that there isn't a huge ecosystem of libraries available, BUT the standard lib is pretty damn great, and there are more and more people coming to the language every day.
My favorite thing about go is it's overall sense of boringness - Go code seems very predictable. There's a culture of digging into the source throughout the community, and tools like go fmt & go vet ensure that most code looks similar.
It'd be worth spending a week with it to write something useful to get a sense of whether or not you truly like it, but my experience has been very positive so far.
My problem with it is how frustrating it is to write when you're not very familiar with it, but I suspect that's more of a generic complaint about learning a new language rather than soecifically about Go. Every line I write, I go "argh, I wonder if this is the idiomatic way to do this" and I get frustrated a lot.
I love the features, though, especially the concurrency ones. It was conceptually trivial to write a multicasting TCP proxy in it.
I had the same problems when I first started learning the language, and while I'm certain I've got a lot more to learn I found that making a habit of reading lots of source code made a huge difference.
After a little while you start thinking about "can this code be clearer? Are the intentions obvious?" and that makes the code much easier to write.
Go is incredibly easy to refactor, so instead of worrying about being exactly right, you can focus on "is this easy to reason about?". My experience has been that this process will get you very close to idiomatic code on its own.
I'm not so much frustrated about being exactly right at a high level, since I am experienced enough with other languages to get the general architecture down correctly. It's more like "How do you declare a slice of channels of channels of ints? Do you make() it or not? If you want to pass a channel, do you pass a pointer or not? How do you pass and reference a pointer? Do you use make in the outermost scope? How do you iterate over a channel but still handle a close?"
It's stuff like that, things I already know how to do in other languages but whose syntax eludes me in Go. I think all I can do is power through it until I gain some familiarity, though. Good thing the people in the IRC channel are amazingly helpful.
The team working on Go regularly rejects proposals that make the language more complex just to save a few keystrokes. They and most experienced Go programmers value the simplicity of the language. Syntactic sugar is routinely rejected out of hand. The increment operator (++) isn't even allowed as an expression because it is too easy to make confusing and error prone code. (you can still use it as a statement, you just can't do like foo[a++]). I wouldn't be worried about the language increasing in complexity much. :)
I think, the best time to find hackers would be before killer applications[1] written in that specific programming language starts to appear. After that, time will pave way to The Go paradox[2].
The best places to find these people would be golang-nuts mailing list, /r/golang, #go-nuts irc etc.
After that, time will pave way to The Go paradox[2].
I am not sure.
Most people who know the important low-level languages well, are not likely to be a fan of Go. Seasoned C++ hackers will miss templates dearly (no, interfaces are not a replacement for templates, they are a replacement for abstract base classes) and C/C++ programmers dislike the lack of control over memory management. If you are using C or C++ in 2012, you probably have good reasons and Go mostly sacrifices the advantages of C and C++.
Someone who is familiar enough with Haskell, ML, or Scala, will dislike the fact that Go practically ignored (or rejected?) two or three decades of research an programming languages. From the perspective of PL research, Go is a weak language.
In other words, the low-level and strong typing crowds are not that much interested in Go. If there is a new imperative language that does interest them, it is probably Rust.
The question is, who does switch to Go? One would guess that these are mostly Python and Ruby programmers who have never written much C, C++, or Haskell, and are looking for something faster and compiled. Yes, this is a generalization, and there are plenty of exceptions. Not exactly the 'Python paradox', 'better than the rest', programmers.
Following the Google+ community, discussions on HN, and to an extend the Go mailing lists, confirms those suspicions. There are lot of grandiose claims supporting Go (one of my personal pet peeves are people claiming that 'Go interfaces are like Haskell typeclasses'). But if you look at the language spec, there is not much interesting. Goroutines are nice, but they are just green threads. Channels have been done elsewhere.
Go is just a very boring language (which isn't necessarily bad), pretty much like Java, without the good package management (no versioning), good IDEs, broad library support, or a performant garbage collector.
Boring languages attract more mediocre programmers than great programmers.
Edit: if you downvote, please, at least leave a comment ;).
I would add a bullet point to the list of reasons I like go: "Boring to people who bring up Haskell in every programming conversation" ;)
Seriously though, there are huge classes of problems in which the "interesting" part of the problem isn't the software that gets written but the business needs it solves. I am a fan of functional programming (I started the Clojure subreddit, and do a lot of "for fun" programming in it), but I've never run across a problem at my business where I felt like I needed to crack open Okasaki's book, or thought "this would be easier with an applicative functor".
Something I've enjoyed about learning Go is the open & accepting nature of the community; I don't think I've ever heard someone called "mediocre" because of other languages they use.
I am happy to feel like I don't have to be an incredible programmer to read the source code of the language I use, or the libraries I pull into my projects. I just want to get shit done so I can work on the problems that I find interesting, and for lots of us, that's just not going to be yet another implementation of datalog.
I can't downvote but I'm using C/C++ in 2013 instead of Go simply because Go is not portable enough. There is currently no PowerPC port and that is still a requirement for me.
> no, interfaces are not a replacement for templates, they are a replacement for abstract base classes
Interfaces aren't a replacement for templates, but they aren't a replacement for abstract base classes either. Interfaces in Go provide polymorphism through structural sub-typing. My limited knowledge of abstract base classes says that these are very much not the same.
> Someone who is familiar enough with Haskell, ML, or Scala, will dislike the fact that Go practically ignored (or rejected?) two or three decades of research an programming languages. From the perspective of PL research, Go is a weak language.
I am a Haskell programmer, but that crowd is impossible to please unless you've provided every PL feature out of research in the last few decades. I've seen virtually no appreciation for simplicity of language design as an entire unit.
> If there is a new imperative language that does interest them, it is probably Rust.
Yes. I can't wait for Rust to get a bit more love in the documentation department. Pattern matching? Algebraic data types? Thread local storage? Type classes? Yes please! Where do I sign up?
> The question is, who does switch to Go? One would guess that these are mostly Python and Ruby programmers who have never written much C, C++, or Haskell, and are looking for something faster and compiled. Yes, this is a generalization, and there are plenty of exceptions. Not exactly the 'Python paradox', 'better than the rest', programmers.
In my experience, most Go programmers are in fact coming from Python and Ruby.
The premise of the "Go" or "Python" paradox is that skilled programmers tend to be the first ones to adopt new languages. Then the less-skilled programmers follow when there is sufficient buzz. I think that if one accepts that premise, it is applicable for Go.
> one of my personal pet peeves are people claiming that 'Go interfaces are like Haskell typeclasses'
That is annoying, but completely understandable. They are deceptively similar on the surface. But I don't think this kind of confusion is unique to Go. You'll see it everywhere.
You know what else people confuse? That Go interfaces are just like abstract base classes! :P
> But if you look at the language spec, there is not much interesting.
That's kind of the point. If you don't accept the overall simplicity of the design Go as a feature, then I can't blame you if you dismiss Go. If all you want to judge a language by is whether it includes cool and exciting new features, then Go will never be a good choice for you a priori.
> Go is just a very boring language (which isn't necessarily bad), pretty much like Java, without the good package management (no versioning)
I am utterly baffled. Go's approach to packaging is literally the best tool of its class that I've ever used. The Go tool militates toward convention rather than providing a dizzying array of features. This makes it strictly less powerful than other packaging tools, but god dammit, it makes it dead simple to install packages.
You want to try my window manager, which is roughly 30,000 LOC (including my X libraries)? If you have Go installed: `go get github.com/BurntSushi/wingo`. That's it. You're done. I just ran it on my system, and it downloaded, compiled and installed my window manager---along with all of its dependencies---in less than 30 seconds.
You might say---other build tools can do this! But do you know how many lines of configuration I had to write for any of this to work? None. I didn't specify dependencies. No strange command line flags. Nothing. The common case Just Works.
> Goroutines are nice, but they are just green threads. Channels have been done elsewhere.
This is a vast understatement. Just green threads? And please, tell me, what other mainstream language supports green threads? I know Haskell and Erlang do. Rust will (yay). Anything else? No? (I know Java doesn't, but I can't remember if this is a limitation of the JVM or if Scala or Clojure have green threads). Go does. That's a pretty big deal. Go makes a solid concurrent style of programming in a C-like language virtually free. Sure, everything is still mutable, but there are powerful idioms that---in my experience---militate against race conditions. It's not as good as Haskell/Erlang/Rust in the compile time safety department, but I'll be damned if it isn't loads easier than my other choices: C, C++, Java, Python, Ruby, Lua, blah blah.
> Boring languages attract more mediocre programmers than great programmers.
And close minded folk think they have all the answers. It's possible for people to enjoy using more than one tool. I'm a hacker, and I love good tools. Go is a great tool. So is Haskell. I hope that Rust will be.
You know what else people confuse? That Go interfaces are just like abstract base classes! :P
I think you are confused by abstract base classes in Java. In C++, which has multiple inheritance, a class can inherit from multiple classes. An abstract without implemented methods behave like an interface, it specifies what deriving classes should implement. The largest difference is in implementation: in C++ a base class pointer is just that and methods will be looked up via the vtable, in Go the interface-typed 'pointer' is actually a type pointer - instance pointer tuple (which is ugly, because it clouds nils). And in Go you do not have to specify the interfaces being implemented explicitly. Some see that as an advantage, others as a disadvantage (since a struct + functions can accidentally implement an interface, while not implementing the intended semantics).
I am utterly baffled. Go's approach to packaging is literally the best tool of its class that I've ever used.
No version management. Fun for hobby projects, a nightmare for large mission critical programs.
This is a vast understatement. Just green threads? And please, tell me, what other mainstream language supports green threads? I know Haskell and Erlang do.
Many languages have green thread implementations (Ruby 1.8, Python, etc.). But there is a varying amount of multiplexing to native threads and some implementations are hampered by global interpreter locks, etc. In fact, even old Java versions implemented green threads, but they were replaced by native threads.
> And in Go you do not have to specify the interfaces being implemented explicitly.
This is precisely what I meant by "... [interfaces] aren't a replacement for abstract base classes either. Interfaces in Go provide polymorphism through structural sub-typing."
Whether it's a good thing or not, it drastically changes the way they are used.
> No version management. Fun for hobby projects, a nightmare for large mission critical programs.
I use the `go` tool for more than hobby projects.
You are re-stating what I already acknowledged. What point are you trying to convey? I said the `go` tool was strictly less powerful, but that it was awesome for the common case. If you don't think that's worth anything, then I'm not sure what else to tell you.
> Many languages have green thread implementations (Ruby 1.8, Python, etc.). But there is a varying amount of multiplexing to native threads and some implementations are hampered by global interpreter locks, etc. In fact, even old Java versions implemented green threads, but they were replaced by native threads.
So........... Go wins here.
Do you really want to have a conversation? Or do you just want to mirror everything I said right back at me?
You can look on the google groups, called go-nuts, and see how many devs are subscribed.
I wouldn't worry about an active market of Go devs to hire. If a language is any good, it'll attract developers. If you're a programmer, you should try out the language to not only do things you can do in other languages (to see how it fares), but more importantly, "What are the new things I can do with Go that use to be hard, but are now easy?"
Most of the comments here generally rave about Go, but what would be more useful to us is things that people found not to be so great in it, like michaelfairley's comment. I'd like to know what Go isn't good for, to avoid spending ages writing something in it because I like its features only to discover it can't easily do something I want.
I still don't see the use case for web app or web game development in Go.
Go ahead and make a mini Go app, re-implement half the features that Express in Node has, then benchmark the 2 with real data using the same data and templates.
Come back when you see that once you start pulling records in from mongodb or somewhere else and start rendering either server side templates with this mongo data or serving json back then the performance differences of the 2 frameworks begin to disappear.
Node will perform better under high concurrency too for most sized responses.
So where's the motivation to switch? If I switch to Go then I have to learn Go + I'm still using Javascript on the front end.
If I stick with Node then I can use my JS knowledge on both ends. This is a really big deal for day to day web app programming and is a deal breaker for html5 games.
Go cannot be taken seriously to be used for web apps until it offers actual performance gains over JS and gets something that lets you write Go but it spits out JS for the client, sort of like Java has GWT (ps. that bombermine mmo uses GWT).
There's also a serious lack of good light weight web frameworks for Go. None of them come close to what Express does for Node, and I'm not the only one who thinks Express is really close to an excellent mix of features without getting in your face.
It's not really close to what express does but it's better than nothing. Then I added in my own etag generator using the same method that express does (it gens it off the body length) for responses > 1kb.
Then I benchmarked each route 3 times with ab using:
-n 7500 -c {50, 250, 750, 1500}
I ignored the first and averaged the last 2 results.
I did this on a local VM locked down to 1 CPU with 512mb of ram with a c2d 2.13ghz CPU and a 7200 rpm sata HD.
Then I did the same with express using just bodyParser since neither setup had session support. Go didn't have a Redis store that was capable of working with the Gorilla session lib so I didn't use sessions on both setups.
I used the native mongodb driver for node.
Express was for the most part 10-15% faster where faster is more requests per second served. The latency was back and forth. I feel like the latency @ 99% was tighter with Go once the concurrency got really high but the amount was not enough to matter.
For example once I got to the higher concurrencies both were taking a ridiculous amount of time (over 7 seconds) on my old crappy desktop. Loading in 5.5 seconds instead of 7 seconds is not really "better" since it's abysmal on both.
Go is much better at responding with large amounts of data when the database call is eliminated. I can only assume its ability to deal with large strings is leaps and bounds superior to v8 which makes sense to me.
The thing is though, that's pretty much irrelevant. If I was going to serve static content I would be using S3 or nginx. If I'm serving dynamic content then I'm likely pulling this in from a database.
Go is much better at responding with large amounts of data when the database call is eliminated. I can only assume its ability to deal with large strings is leaps and bounds superior to v8 which makes sense to me.
In my own micro-benchmark, I've seen that BSON decoding takes big chunk of time when using mgo. That should explain why the go version got faster when DB access was removed.
This shouldn't come as a surprise as the node.js driver uses a BSON parser written in C++ by default.
It wasn't just a small difference though. The difference between returning 10kb of json from a function vs 10kb of json from mgo was insanely different.
I don't think it's because the bson C++ implementation is so much faster than Go.
I think it's because Go is clearly faster than JS but it doesn't matter once you introduce db calls.
It's sort of like using "for in" vs "for" in JS in the browser. It doesn't really matter which one of them might be faster than the other, as soon as you touch the DOM the difference becomes meaningless and if you jsperf it with DOM touching the results will be the same.
In my mind the big advantage of Go over Node that is sometimes overlooked is that your code in Go is written in a largely serial manner with no callbacks. With Go you don't have to deal with a lot of callbacks when doing I/O since goroutines are multiplexed on the underlying threads.
If you need performance why not go with scala. The play framework is super easy to use. Anyone who is familiar with mvc will pick it up very fast. There is also Martin Odersky's course which is a great intro.
I'm sorry, but as I've tried to learn Haskell in 2 month sprints 4 separate times and failed, I can not in good conscience recommend Haskell, ever. I like the language allot, but even the programmers I believe are extremely talented just cannot learn it, let alone 99% of people I have to work with who simply can not even begin to make use of the language at it's most basic form.
A professor I knew, who was easily one of the more decorated in my university, claimed he knew Haskell.
I had used Haskell to parse biomedical data for my course on biometrics, as the data was inconsistent and full of errors, the correct design was to create a monadic structure. I consulted that professor, and he was flummoxed, just on the basic structure of the program (which was done in a basic top down style of declaring the types and breaking large functions into small ones).
I fully accept my inability to use the language in a useful way may just be symptomatic of me being an idiot. I fully accept that my professors inability to understand the language in a any way may be symptomatic of him being an idiot.
But as big a failure as I am at learning this language, I can't imagine the result of tasking someone who doesn't enjoy programming with maintaining Haskell.
Just considering the language, then I think Scala is considerably easier to learn than haskell _if_ you're from an OO background. It's a multi-paradigm language making it easy to use it like a better c++11. However, idiomatic Scala is functional, and so you're pushed in another direction by the community (but, importantly, not forced). However, starting with a blank slate, then Haskell might be the easier language to learn.
But if we consider the resources to learn the language along with the language, then I think Scala dominates Haskell. Haskell was painful for me to learn because to become proficient I had to trudge through not only books but wikis, blogs, and code. There is nothing like Odersky's Scala book in Haskell. Learn you a Haskell, the Haskell wikibook, and Real World Haskell are all _terrible_ at preparing someone to become a proficient haskeller because while they show you the language they don't train you to think functionally.
In imperative languages you're giving a lot of sequential instructions to a robot. In functional languages you're programming the robot to understand a new language, and then you describe the way things ought to be in that language.
This is another thing I persistently thought while I was learning Haskell
"It's a paradigm shift, you're used to programming
imperatively, this is not imperative. Think back to when
you first started programming, you got caught on doing
simple things, right? This is the same."
On sober reflection, I don't buy this logic any more. Haskell's ability to be generic is really cool, so cool that it has a massive standard library of itemized, tried and tested bits of logic that can be used anywhere, and I do mean anywhere. All of which you as a new programmer are tasked with getting acquainted with. As a new programmer you must abstract your program out in a way that fits one or more these component pieces, that can fit the standard library. Ouch.
Of course, this library only gives you a toolbox to cover some fundamental logic, you can express really interesting things in short lines if you're skilled enough to abstract your problem out into general behaviour. Even I got this far, but when the problem your working on is best modelled through state, which is basically everything, you now have to understand monads.
What portion of the population do you think can utter these words confidently? "I Understand Monads"
Haskell provides no ramp up, there is no learning curve. I don't believe Haskell's problem is that it's different, I believe it's problem is that it's different and difficult.
It is different and difficult. I think that's because functional programming isn't simply a sideways step from imperative programming, but is instead a level of abstraction higher than imperative programming.
Hofstadter says analogy is the core of cognition. We tie unknown things to known things to understand them, and I think that's why you get all these bad analogies where people try to tie the more abstract concepts of fp like monads to everyday things ( "monads are like burritos," for example).
And this really doesn't make sense because monads and such are pure abstractions. How do you tie a pure abstraction to something concrete? It's like saying zero is like a burrito.
The better analogies tie pure abstractions like monads and arrows to other abstractions that you already understand. For instance, Odersky trains you by iteratively refactoring imperative Scala code into more functional code, and thereby gradually carrying you up the ladder of abstraction.
I'm still waiting for the day when I can readily recommend OCaml to people. It's a very nice language, supports functional, imperative and OO programming, has all the nice goodies that PL people want (sum types, parametric polymorphism, GADTs), while not being completely alien as Haskell can sometimes be to people coming from a more traditional background.
What OCaml lacks, is a more modern implementation; I hear that the company OCamlPro are currently implementing a per-task GC strategy to allow for better multi-programming, there are alternatives to the rather minimalist standard library (Jane Street Core and Batteries Included), OPAM is poised to become the de factor OCaml package manager. I'm still hoping that built-in Unicode support will become a reality as well.
Haskell is a much better choice than Scala, as long as JVM isn't required.
Haskell is much cleaner than Scala. But I think most people will get stuck reasoning about laziness (which is necessary to avoid space leaks). Another problem is that many modules require extensive use of the type system and advanced concepts to use (monads, arrows, lenses, existential typing, etc.).
I think that on the JVM Kotlin is a good candidate for eventually fixing most of Java's immediate shortcomings. Scala is there for people who'd like to go all-functional (regardless' its complexity). One of the nice things is that you get at least some amount of interoperability, e.g. one can perfectly write Play applications in Java and still get many of the benefits of Play.
> Haskell is much cleaner than Scala. But I think most people will get stuck reasoning about laziness (which is necessary to avoid space leaks). Another problem is that many modules require extensive use of the type system and advanced concepts to use (monads, arrows, lenses, existential typing, etc.).
Not to mention that many modules require various GHC extensions.
I'm not so sure about Kotlin. From what I can see, it's pretty straightforward, with no risk or ambition of achieving the anxiety-inducing Scala method signatures. On the other hand, it seems to be seriously lacking in the marketing department, which can often be enough to push forward a language even when a better option is available.
Scala's syntax is not as nice as Haskell's, but it's quite consistent and not crazy at all, certainly it's not worse than Java's.
As a programming language, Haskell has many interesting features, and I would happily use it in various context, including as language of choice for a first "Introduction to Programming" course, but Haskell has several problems too. The most glaring is the 2nd rate support of state. The state monad has several good features, but in particular, it lacks a destructor, so local state use can't be hidden, even when global behaviour is purely functional. Moreover, modularisation is better supported in Scala than in Haskell.
I've looked at it a number of times, I don't like the syntax. When Java came out in August 1995 I was one of the first downloaders (and not even a fan of Sun in particular at that time, just interested in checking out Java) and it was clear just looking at it I would like it.
I was kind of disappointed that they went with a flat file approach for permanent storage, especially because the documentation for the typical RDBMS interaction isn't exactly comprehensive.
Go still hasn't found a niche to be useful to. Nobody's giving up 30 years of C for systems programming, nobody's going to use Go for web apps when higher level languages are clearly more practical, nobody will give up Haskell for scientific and massive parallel programming. All in all I think Go is an interesting experiment but it serves no purpose that I can use right now
Go fills the same niche as node.js: high performing API servers talking to some frontend: a "proper" webserver, thick in-browser webapp, a mobile app, etc. And it's a pretty damn good alternative when you compare the clarity of goroutines with the typical mess of Javascript callbacks.
Oddly enough, I know several people who are giving up 30 years of C and Fortran programming to use Go because they find its features sufficiently compelling--and they're changing minds throughout the organization.
For about two years, many of the people I work with have been using Go almost exclusively because, while simple and fast like C, the things it adds are so useful we can't imagine trying to hack similar functionality together with C libraries. Things like built-in maps, slices, multiple returns, lambda functions, channels, goroutines... these are all things you can accomplish in C, but it's so much more painful (see: homebrewed hashtables, do-it-yourself pointer management on a big array, returning structs, function pointers, some sort of mutex abomination to replicate channels, pthreads)
Go was designed for the above-OS, networked systems programming niche at Google: new database engines, distributed filesystems, web servers (as opposed to web apps), and other similar projects. I would not write a wiki app in it, but certainly the next Apache or Nginx replacement.
And although I haven't tried it out myself yet, it does seem very promising for such use cases. You don't have to "give up" 30 years of existing C code if you are just using it as libraries and OS calls, not rewriting it.
> I would not write a wiki app in it, but certainly the next Apache or Nginx replacement.
I wouldn't. Nondeterministic garbage collection in a web server like nginx (as opposed to an application web server like Jetty) makes me very nervous. The HTTP (or pick-your-other-TCP-protocol) lifecycle is well-understood enough that you should be able to handle your own memory management.
There are lots of things in Go I like, but for me they're coupled with questionable abstractions that make it difficult to rationalize over C++.
Actually Go GC is quite easy to control. If you know your butt from your elbow you can write code that doesn't GC at all.
I really don't have a problem with GC though. Its easier to optimise a GC than to fix memory and reference counting bugs. Memory management is not a problem I want to be dealing with after 60-odd years of computers being around.
> Its easier to optimise a GC than to fix memory and reference counting bugs.
I don't agree. If you are competent enough to be needing to write your own web server, memory management should be utterly trivial.
There are many use cases where you do not need to really balance bleeding performance against programmer conveniences. Something like "Apache or nginx" is without question one of them.
I'm curious, why do you think higher level languages are more practical? Other languages at present have better tooling and libraries for this, but there's really nothing in the language itself that makes it hard to do web dev, quite the reverse, in fact having played around with a few personal projects and given the use it has had so far at google, I suspect golang may well find its niche as a server side language. Have you tried it?
I will gladly give up C for systems programming for new projects. Go would have made an interesting choice over Python for the non-performance-critical parts of BIND10; I would certainly have studied the source closely. I can see myself writing things like Postfix policy daemons in Go. Heck, if I had a side project named "write a SMTP/IMAP server", Go would be my first choice.
I do have a side project of writing a DNS server, and my scribbled notes for it say to use Erlang for the protocol speaker and Go for the control plane.
I suggest that what Go needs is some kind of killer project that everyone can learn from. C had UNIX.
The niche I think go appeals to is Python/Ruby/NodeJS developers who are intimidated by systems programming (eg: C-style threads, manual garbage collection) but still want to work in a statically typed environment.
Goroutines and channels in particular are an interesting and useful abstraction away from threads and communication between those threads.
A higher level language would've been worse for developing my web app, niflet.com. I did the prototype in PHP and found Go to be easier to code in, much less coding overall, and at least 10X better performance. I didn't have to deploy a separate web server either.
> One can easily program is if [sic] it were C, using templates to avoid ugly macro mess for generic algorithms and types.
Did you mean "as if"? If so, that's exactly what Torvalds objects to -- the things about C++ that supposedly represent improvements over C. He goes on about how many of the conveniences of C++ -- like the STL -- aren't as wrung out as most people think and don't actually work as intended.
I don't necessarily agree with his position in all respects, but some of the enhancements in C++, aren't actually enhancements.
For scientific computing, you have an insanely well designed languaged, with it you can run extremely fast computations, optimally tuned for your hardware even on multicore systems. The language is Fortran.
Yeah, C/C++ or Python/NumPy, Haskell is still a niche language that some people like to talk about, but all numbers and statistics on the matter seem to indicate it's never actually been preferably used to solve problems in any domain.
Couldn't you also say "I don't see how C was ever aimed at replacing assembly for systems programming, heck the C runtime and compiler is written in assembly."
This argument is getting old. What was the first, the egg or the chicken? Was the first C implementation passed down on stones drawn from the void of the Universe? At some point bootstrapping was needed for the implementation to be self hosted. That goes for every supported platform.
Of course. But for the moment, being self hosted is just reinventing the wheel when there's so much existing infrastructure. That being said, it is difficult, probably impossible, for Go to be a C replacement, but you're using the wrong argument (the current canonical implementation).
Why do people choose 'Go' over Scala? The latter is a 'better' choice (in my opinion) for web applications and add in the play framework, you've got an ultra-fast, scalable web app. running in minutes. I do admit that Scala has a steeper learning curve, but my guess is that it's worth it.
Can anyone explain WHY Scala seems to be ignored by most of the programming community, especially here on HN, where everyone seems to be in favor of either Node.js or Go... ? Is there anyone who can provide some constructive negative feedback regarding Scala (apart from the learning curve) over GO?
Because it requires an entire JVM of baggage, is terribly complicated and doesn't really give any benefits over anything else.
Its like a Swiss army knife with a million blunt obscure tools rather than 5 useful sharp ones, or a crazy girlfriend who has three violent ex husbands who keep coming round to your house and lives with a crackhead.
Go is a trip to your Volvo dealer - uneventful but you get what you want at the end of the day and get where you want to go and when you're done, you're done.
It's false to say that Scala "doesn't really give any benefits over anything else". For a start Scala programs tend to be 1/3 of the size of comparable Java programs, with all the concomitant advantages that brings.
Do you write rants like this for every article on HN which is not about Scala? As far as I can tell, different programmers like different languages for different reasons.
I don't write webapps, but if I did, I would probably choose Clojure or Haskell or Python. You should learn to understand that by doing so, I am not insulting you or your language of choice.
Go and its tooling have a strong "straightforward" aesthetic that appeals to some people. Languages that go after power and ecosystem are in a more crowded battle for mindshare.
> Go and its tooling have a strong "straightforward" aesthetic that appeals to some people.
Yeah, specifically I see it as part of the "worse is better" school of design, of which I am a great fan. A sort of 'cat -v' aesthetic. I find that working with a language, or on products, that have embraced that mentality is just so much... calmer. It puts me at ease, for lack of better terminology.
Gopher here. I'll try my best as to why I chose Go over Scala; this isn't meant to be "why I think Go is better than Scala", it's "how Go kept me interested from zero to gopher, while Scala failed to attract my attention".
Scala didn't keep me curious for long enough to get good at it. I took a look at some examples, flipped through a textbook, and just came to the conclusion that there were way too many features and it appeared to be too clever for me to care. Things like impressive one-liners don't impress me; they do the opposite. That it's built on the JVM doesn't particularly appeal to me because I don't have any existing JVM-dependent projects. Examples like this: http://www.scala-lang.org/node/225
/** Turn command line arguments to uppercase */
object Main {
def main(args: Array[String]) {
val res = for (a <- args) yield a.toUpperCase
println("Arguments: " + res.toString)
}
}
the toUpperCase method being called without parens is bothersome to me, since it makes it ambiguous what is and is not a function call. The for loop being an expression is strange to me; it's a construct that appears to add no value to the programer, at a significant cost of clarity. It must make me seem very stupid to argue against looping constructs as simple expressions, but I think this type of notation is unnecessarily terse. Go doesn't have this type of thing, because the language is designed more for clarity than for terseness. I don't think that this is elegant:
for (a <- args) yield a.toUpperCase
I think it's far too clever. Beyond the method call, another thing that appears to be hidden here is the creation of the target list to which the uppercase letters are being stored. How many memory allocations are there in this statement? What if the body of that loop is conditional and we don't know how much space we need in advance? Yes, it's nice to look at, and I can see how it might be exciting to understand that for the first time, but... everything that it adds seems to be completely unimportant, but the operations that much be happening have been hidden from view. Great, we've saved a bit of typing, but in the process, we've lost a lot of understanding about how our program behaves.
Then there are other simple things. I really enjoy that curly brackets are mandatory on looping constructs in Go; I noticed that Scala has the feature that you can leave them off and it only includes the next statement. I find that feature profoundly annoying and prefer that it does not exist. I really like the way the tooling enforces formatting. I really like the way that Go is militant. When I write Go, I feel like I'm at work assembling an information processing machine; I don't feel like I'm writing poetry. I don't want to feel like I'm writing poetry. I'm happy to be making information machines, because that's the honest truth of the craft. The poetry lies in what those machines do; the art is in the output. To me, writing a boring program whose code is very clever is like writing a boring poem in beautiful calligraphy and arguing that the beauty of the calligraphy makes the poem better.
So that's why I went with Go, and not Scala. Of course, there are things I wish we had; specifically operator overloading and something akin to generics, the former we almost certainly will never get, while the latter remains an open question. A part of me misses having properties or Python's decorators, but... these are features that I've found can easily create maintenance problems; features that have caused trouble for me in the past.
Go, of course, has its warts (some would argue that the language made entirely of warts), but while learning the language I always got the feeling that the things that were annoying were good for me; that the warts were like being told to eat your vegetables. After a year and a half of programming Go regularly, I've found that to be largely true. My old code is much easier for me to go back to than the equivalent in other languages, and I've found my Go projects to be very easy to maintain, overall.
Go's code is the right level of terseness for me. It's far, far shorter than equivalent Java code and it's very clear. To me, elegance is clarity. To others, elegance is terseness. It's all a matter of opinion. I think you'd be hard-pressed to find someone that chose Go over Scala because of the merits of what can be built with one tool over the other; I reckon they're quite comparable in this regard.
"I don't want to feel like I'm writing poetry. I'm happy to be making information machines, because that's the honest truth of the craft. The poetry lies in what those machines do; the art is in the output. To me, writing a boring program whose code is very clever is like writing a boring poem in beautiful calligraphy and arguing that the beauty of the calligraphy makes the poem better."
Speaking as someone with a bachelor in fine arts, this rings very true for me. In Dutch, when an idea isn't working out, we have a saying: "het komt niet uit de verf," which literally translates as "it doesn't leave the paint."
With the exception of certain modern and contemporary art pieces, a painting is about what is being depicted, not about the fucking paint. The paint matters of course, but it shouldn't take the spotlight (again, ignoring self-referential topics like paintings about the experience of paint).
For loops being expressions is a source of power and uniformity in languages like Scala. It really makes your life easier in many situations. It's an unusual way of looking at loops when you come from a background in imperative programming, but once you realise that imperative programming is not the only way to compute, your life as a programmer becomes easier!
Maybe, at some point, if you have spare time, I recommend that you give a modern language like Scala, Haskell or ML/Ocaml/F# that don't distinguish statements from expressions a second chance.
I have not written my first Go (or Scala) program yet, but I have written some F# code and loved the language (and the fact that everything is an expression too). It does have som complex features, and special syntax appears very often, but after reading just a bit of documentation, I can easily understand the core concepts and syntax.
On the other hand, Scala gives me a completely different feeling: when reading the docs and samples, I often ask myself:
How can I mentally parse this?
It's nice that I can abbreviate some common constructs (when writing), but when reading code, how can I tell which concepts are being used? How do I look up these operators when they could come from anywhere (global, first operand, second operand, implicit conversion, etc.)
How do I know when parentheses, dots, curly braces, are mandatory or optional? Could the compiler misunderstand me in complex situations? Where does this construct really end if so many things are optional? At least F# uses indentation, so I know the compiler will warn me if I wrote something that is not quite right according to the precedence rules.
There are too many implicit things going on, how do I know which meaning of _ (underscore) is meant here?
I'd say this is largely a non-problem. If you already know F#, then Scala is a much simpler, more consistent language.
In a way, Scala seems to be a refined, better designed version of F#.
For instance, F# has support for functional and object-oriented programming, but most people I spoke to recommend just ignoring the object parts. That's certainly my impression, too. Compared to Scala, F# didn't manage to combine FP and OOP into a single, coherent approach. You have more or less ML's type system with the object stuff bolted on.
Another example would be that F# has tons of features where a single one could suffice. Consider the Unit of Measurement stuff, the various forms of (computation) expressions and type providers. Scala can do all of that and a lot more with "just" macros.
> It's nice that I can abbreviate some common constructs
Not sure what you mean with that.
> How do I look up these operators when they could come from anywhere (global, first operand, second operand, implicit conversion, etc.)
Not really. There are no operators, everything is a method invocation. The method is either defined on the type of the left, or added by an conversion from that type. That's it.
> How do I know when parentheses, dots, curly braces, are mandatory or optional?
Method calls with one argument can leave out dot and parentheses. If a method has a side effect, you define and call it with parentheses, otherwise you leave them out.
> There are too many implicit things going on, how do I know which meaning of _ (underscore) is meant here?
People love to make up scary examples, but I have never seen any actual misuse of implicits in real code. The meaning of the underscore doesn't change, it is always the same: "There exists something, but I don't care to give it a name."
> If you already know F#, then Scala is a much simpler
Well, F# does seem to have a lot of "bolted-on" features, but Scala always gives the impression that things "come out of nowhere", e.g. a simple underscore turns the whole expression into a lambda! It looks neat, but I will need some practice to get used to things like this. But, as I said, this is just a superficial analysis, some thing we can only learn after some practicing.
> Not sure what you mean with that.
Braces, parenthesis, dots, semicolons, and IIRC you can use the arrow => without anything on its left side.
> The method is either defined on the type of the left, or added by an conversion from that type. That's it.
Unless it ends with a colon, right?
> Method calls with one argument can leave out dot and parentheses
That's somewhat simpler than I expected. I thought it was something Perl-like or Ruby-like (where obj.method + 1 is different from obj.method +1). There should be some way to get a reference to a method without calling it, that I still haven't learnt.
> If a method has a side effect, you define and call it with parentheses, otherwise you leave them out
Not sure I understand this. Is this the preferred coding style or something enforced by the compiler?
> I hope that helps a bit!
Yes, it helped! Thanks!
Go doesn't have the ternary operator, and I thank the Go gods for that every day :)
Go is good because it's hard to write clever code in it. Go encourages simple code. Clever code is almost always bad. It's hard to understand and easy to screw up. For example, at work we had a bug in production for 5 years that short circuited our authorization code because of an incorrectly written ternary statement. If the author had written a simple if statement, the error would have been blindingly obvious. It should have been caught by tests, but due to how the tests were written, that particular path never got called.
Interesting answer. Those 2 bits are great, had to highlight them...
The poetry lies in what those machines do; the art is in the output. To me, writing a boring program whose code is very clever is like writing a boring poem in beautiful calligraphy and arguing that the beauty of the calligraphy makes the poem better.
To me, elegance is clarity. To others, elegance is terseness.
Good for you, I don't see anything interesting, you own your choice. Just another one choosing a programming language by its syntax. Good for you.
I code in Scala, Python and Ruby, because they bring different things. If I wanted to write purely elegant code I'd do it in OCaml for that matter. When I do simple things or Machine learning things I use python because it's an interesting and beautiful language with a lot of awesome library. When I need performance, strong type system with functional features, and high level concurrency beyond co routines, and parallelism I'll use Scala. Because the jvm is great at those, and Scala suits those needs very well.
So .. Good for you if Go is your language of choice.
If you build a webapp in Go, be prepared to spend a lot of time monkeying around with problems that are solved issues on most other platforms.