Hacker News new | past | comments | ask | show | jobs | submit login
From Node.js to Go (bowery.io)
316 points by francesca on Jan 29, 2015 | hide | past | favorite | 185 comments



I'e been writing my first production-sized Go app over the last few months, and really enjoy it. Some observations:

- The standard library is solid, and I was surprised how well-rounded and mature the third-party library support it. Coming from a Python/Ruby background, that was nice to see.

- I totally agree with the comments on this thread about dependency management. Godep [1] is nice, but it would be great to see a canonical dep management tool for go.

- The tooling for Go is excellent: More languages need something like "go fmt".

- In general the document is solid, but I've found the usability of the generated docs to be poor. You think they could bribe a few Google designers to spend some time fixing that...

- I've noticed a lot of Rust lovers commenting about how great Rust's type system is. It probably is, but I haven't run into any problems with Go's type system. I've found it to be practical and easy to use. The only issue is parsing JSON when you're not marshalling it to struct. They need to fix that (although there are some nice third-party tools to make it easier).

- Go is a minimal language and has been called boring. [2] I don't claim to be an expert yet, but I don't think I've reached this level of productivity with a language this quickly before.

[1] https://github.com/tools/godep

[2] http://stevebate.silvrback.com/go-is-boring


> I've noticed a lot of Rust lovers commenting about how great Rust's type system is. It probably is, but I haven't run into any problems with Go's type system. I've found it to be practical and easy to use.

Go doesn't have generics. To someone coming from a language like Rust, saying that your type system doesn't have generics is like saying your car doesn't have wheels. It's just considered non-negotiable.


> saying that your type system doesn't have generics is like saying your car doesn't have wheels.

To overburden an analogy, it'd be more like complaining that your tank doesn't have wheels[0], or your hovercraft. Go takes a different approach to the same problem (in this analogy, getting from point A to point B).

But really, this is a rather tired flamewar that gets beaten to death literally every time a post about Go makes the front page, and there's really nothing more that can be said about it. Either program in idiomatic Go, which means using the language as it's designed (ie, without generics, at least in its current form), or don't, but it's very tiresome to see this argument rehashed again and again.

[0] https://en.wikipedia.org/wiki/Continuous_track#mediaviewer/F...


> To overburden an analogy

Sorry. In the spirit of Go, you're not allowed to re-use this analogy; you're going to need to write another different one that can perform a similar function.

It's ok if you copy and paste some of the text from the first analogy and structure it similarly, though.


> Go takes a different approach to the same problem (in this analogy, getting from point A to point B).

Go doesn't take any approach to writing generic code at all.


That's the really disappointing part. I've read the thread where the designers talk about implementing generics, and they basically say that every language's implementation of generics sucks, and since they can't come up with a design that's perfect (no codegen duplication, but still all the perf of specialization), they're just gonna punt.

And then the code I've seen is littered with "interface {}".

That's a pretty big thing to give up, and I don't get the point. Something like F# gives you high level features (and green threads if you want) with fair perf, and Rust gives you a fair amount of language with C perf.


I think littered might be a bit strong. I'm writing a service in Go, and have yet to use interface{}. However, you might have to use it more when writing libraries.


That's false. Go has structural subtyping. It enables you to sort collections of things without actually writing a sorting algorithm. Seems like generic code to me.


It has interfaces to write generic code. It doesn't allow you to write your own generic data structures but it's not an issue because it has built-in dynamic arrays and dictionaries. You supposed to use built in data structures most of the time like with python or ruby.


This happens because almost every time there's someone who more or less asks what in the world generics are for since they can do everything they want to with Go's type system. Sure, it's possible, but it's missing the point.


I always saw it as the classical: why do you want a screwdriver to put the screw in place? The hammer should be good enough!

Well, sure, I guess you can pound a screw into things with a hammer but you're missing the point.


Or just build your furniture without using screws, like in Japanese carpentry. When people are already having a decent time building things using the tool, it looks pretty stupid to tell them they've done it all wrong for years in all the decent products they made.


Parametric polymorphism gives safety guarantees that you can't easily obtain without language support. For example if you have a function typed "forall a . a -> a" you know it has to be the identity function (or something that bypasses the typesystem, like infinite loops or a runtime exception).


And in Go since there is no parametric polymorphism you would end up writing either:

1) Methods with names that indicate the parameter types. 2) Method calls on objects to convert some internal struct data from one type to another. 3) Something I haven't thought of that doesn't involve losing a handle on your type.

So there is certainly a loss in convenience, but if you use the type system it can be just as safe as a functional language as far as I can tell. So, yeah, it isn't as intellectually elegant, but it also isn't really that hard to deal with.


No you can't. The point of generics is that you don't need to specify the parameter types - the parameter type is also a parameter. This means that you can write type safe container operations like "map" and "filter".

The only way to write this kind of generic code in Go is to cast everything to `interface{}`, which can't be checked statically.

If you are still not convinced, one of the things you can do with generics is say "these two parameters have the same type". In Go the best you can do is say "these two parameters are subclasses of something", which is less precise.


Yeah I follow you. I am providing ways of trying to work around the lack of a higher level type class system. As a baseline, I would recommend not jumping outside golang's given type system just because it feels inconvenient for the programmer. That means you don't get to write a generic method for, for instance, all integers. Too bad :P This means the programmer does have to do more work, but the type system is always strictly enforced. That is better in my opinion.


Technically a coin should be enough to put a screw in place. winks depending on the size of the screw of course. :-)


Don't worry! All the screws have the same size and your coin is compatible. (Go's builtin data types which have generics)

You want to use different screws? You're on your own.


> To overburden an analogy, it'd be more like complaining that your tank doesn't have wheels

Which would be just as bad as for a car, since the things that drive and guide a tank tread are wheels (drive wheels and road wheels.)


Having written in both Go and Rust, I can see the arguments. Go has a relatively simple, easy to use type system. The problem is that whenever you need to do anything generic, you have to use Go's "any" type, "interface{}", and the reflection system. This results in doing stuff over and over at run time that could have been done once, preferably at compile time. For much web back-end stuff, though, you don't need a really fancy type system with generics. Mostly you're pushing strings around, which Go does quite well.

Rust's type system has most of the bells and whistles of C++, plus some new ones. It's clever, well thought out, sound, and bulky. Rust has very powerful compile-time programming; there's a regular expression compiler that runs at compile time. I'm concerned that Rust is starting out at the cruft level it took C++ 20 years to achieve. I shudder to think of what things will be like once the Boost crowd discovers Rust.

The lack of exception handing in Rust forces program design into a form where many functions return "Result" or "Some", which are generic enumeration/variant record types. These must be instantiated with the actual return type. As a result, a rather high percentage of functions in Rust seem to involve generics. There are some rather tortured functional programming forms used to handle errors, such as ".and_then(lambda)". Doing N things in succession, each of which can generate an error, is either verbose (match statement) or obscure ("and_then()"). You get to pick. Or you can just use ".unwrap()", which extracts the value from a Some form and makes a failure fatal. It's tempting to over-use that.

The lack of exception handling in Go yields too many "goto" statements. There's also a tendency to turn the panic/recover mechanism into an exception system. This has roughly the problems of C's" longjmp".

As a practical matter, Go now has most of the libraries you need for server-side programs. (Not GUI programs, though.) Rust has only very basic libraries, and they're not stable yet. The language hasn't quite settled down. People are writing and porting libraries at a good pace, and this problem will be solved.


> I'm concerned that Rust is starting out at the cruft level it took C++ 20 years to achieve.

That is the core reason why there are no generics in Go. Not because the Go team thinks they're a terrible idea, but because they think cruft is a terrible idea.

The default answer to a new feature is "no". When everything seems to be going fine without generics (except for internet flamewars), the answer stays "no".


The reason there are no generics in Go is because nobody has implemented them in Go (or presented a concrete proposal for implementing them, i.e. something less vague than "just do what C# did" while ignoring that C# is not AOT compiled). Thre are some monomorphizing preprocessors but they tend to punt on the interaction betweeen generics and the rest of the language.

I find the community's insistence that Go does not have them because they somehow make programming worse to be fairly ludicrous, when there are much more practical reasons. Obviously you can write useful code without generics (C does not have them), but that does not make them useless, or "cruft", or an undesired feature (unless you simply choose to believe that every single person complaining about them does not use Go): you can also write useful code without many other features that Go does have.


> while ignoring that C# is not AOT compiled

https://msdn.microsoft.com/en-us/vstudio/dotnetnative.aspx


Does this take significantly longer to compile than regular C# code (I can't imagine the answer is no)? If so, it doesn't really address the concerns Go's implementors brought up, which precisely revolved around the compile time : runtime performance tradeoffs that the JIT compiler helps mitigate for C#'s generics.


Idiomatic Rust uses try!. It is a less verbose version of the most common pattern of error handling in Go. You have not programmed very much Rust and are not yet familiar with its idioms, but that is by far the most common and avoids all the problems you just described.


"try!" is close to something one might call "cruft". It tests a function for an error value, and if it gets one, it returns from the containing function. "try!()" is written like a function call, but it doesn't work like one - it can execute a return statement. That's outside the normal semantics of the language. This is the only macro in the standard macros with such semantics. Fortunately. This is a capability which needs to be used with extreme restraint. Writing a macro "try_except_finally!(maincode, exceptioncode, cleanupcode)" would probably be a bad idea.

There was at one time a fad for extending C with macros like that. Fortunately for program readability, it didn't last.


`throw` in Java's exception handling also prematurely exits a function. So?

While `try!()` is a macro and not a core language feature, most of the macros in the standard library can be treated as such. So a Rust programmer will know that `try!()` can return, just like a Java programmer knows that `throw` returns early.

Besides, macros are syntactically distinguishable in Rust. When you see that exclamation mark, you have to rememeber that it's a macro and might be doing arbitrary compile time things along with arbitrary token tree expansion.


Except that in Rust, all macros are syntactically distinguished from non-macros (as well as hygienic, unlike C macros), and try! is extremely common (so the claim that people won't know what it does is questionable). I agree that macros like this should be carefully considered, but I think experience has already shown us that try! is perfectly fine.


FWIW Go does implement a significant subset of generics in a type-safe way. For any parametric type P[T], if P has no public methods or fields that mention T, then Go can implement it by allowing an interface (not necessarily interface{}) type for T. As long as the implementation of P does not upcast T values (something which is generally frowned upon, although tolerated in some circumstances), this will be as type-safe as in any language with parametric polymorphism.

For example, bufio.NewReader would probably, in a language with generics, be phrased as a type with respect to a type parameter. Something like (in bastard Haskell)

    class Reader a where
        Read :: a -> [Char]


    newReader :: (Reader a) => a -> BufioReader a
In Go, it's:

    package bufio
    func NewReader(r io.Reader) *Reader
The interface argument is implicitly a type parameter here.

This subset of generics covers a wide range of software components, even if it doesn't include the usual container types.


I think it's important to think of these features in terms of their smallest possible descriptions. One mistake with Java, I think, is that "inheritance" is how you do both polymorphism and composition (I know you can do either without inheritance, but it's especially a pain to do composition without).

With Go, polymorphism is done with interfaces. Composition is done with embedded fields (and the very convenient method promotion).


> To someone coming from a language like Rust, saying that your type system doesn't have generics is like saying your car doesn't have wheels. It's just considered non-negotiable.

That's ridiculous. Plenty of people can appreciate the trade offs between "no generics" and "generics." There's nothing "non-negotiable" about it.


This was one of my main complaint against Go.

However, I still think the out of the box performance is great and for problems that don't require generics it is a very good option. I especially like the static compiling feature that makes deployments more straightforward. Handling HTTP requests and performing routing, dispatching requests to other services reliable async way is the biggest use case for me using Go. It can totally be written in any other language(Rust), if using generics is a must.


If its not-negotiable, then get over it, and use a language that meets your requirements.


I've never used a typed language at all (only PHP, JS, Python etc). Why is it a big deal? I read the Wikipedia article but didn't understand why.


Say you have a function that can operate on various types, for example you'd have a function in JS like:

  function addKey(input, key, value) { input[key] = value; return input; }
this will work on either Objects or on an Array. But if you have static typing and no generics to make it work you have to either:

- create two versions of the same function, one for Objects, 2nd for Arrays

- use any as a type of input - this will work, but you will loose most of the benefits of type checking, e.g. you will be also able to pass Number as an input and compiler won't complain, it will be detected as error only on runtime and other things (your function will also return any so further on in the program you won't know what type is used).

With generic it's easy, you write the function once and when you call it you tell what types are used:

  // definition:
  function addKey<X,Y,Z>(input:X, key:Y, value:Z):X { ... }
  // call:
  var a = addKey<Array<string>,Number,string>([],0,"fubar");
With this particular example there are probably other ways as well (sum types, common interface) and also compiler may actually detect passing Number as an error (depends how smart it is), but there are more complex cases, where lack of generics will lead to a lot of copy/pasting and boilerplate.


Thanks a lot. That was a really good explanation which instantly made me understand generics. In fact, I think this is an awesome way to learn new languages and concepts. You start with an example in a language you know and reason about the functionality from that.


Guarantees at compile time:

Array<double> means the only element you will encounter is a double.

Array<ISomeInterface> means the only element you will encounter is of type ISomeInterface.

hence, you can express part of some code's requirements via the types that a function,class exposes and/or requires.

these requirements can then be checked at compile time.

without this you have to defer the "checking" to runtime.


I'm sorry, I meant why generics are a big deal. Thanks though!


There are two types of people.


To someone coming from a language like Rust, saying that your type system doesn't have generics is like saying your car doesn't have wheels. It's just considered non-negotiable.

Analogies are almost always useless diversions, but this one is particularly ridiculous.

People are building real, working, successful solutions in Go with rather surprisingly regularity (which, if the comparison needs to be made, they don't seem to be doing with Rust). It is obviously working pretty well, and that "non-negotiable" point turned out to not be a showstopper.

A car without wheels? If we have to abuse analogies, more like a car with a manual transmission. People can have hysterics about how will they ever eat their burger while they drive, but somehow some people manage.


If being able to get things out the door anyway is the standard for "well, guess this language is nice enough!", there goes any argument against JavaScript, or for that matter Go over Java.

I'm one of the people who is currently making a working solution in Go. Are generics the equivalent of missing wheels? Probably not, but I am absolutely finding it a present and persistent pain point that I don't have something like that or even just overloaded function/method signatures, and instead have to frequently repeat a lot of rewritten code scattered full of lots and lots of if/else cases.

Life could be worse. But the fact that people are shipping doesn't mean it's a language in which people aren't finding a specific missing features to be a problem.


If being able to get things out the door anyway

This is specious logic. People are not being told to use Go grudgingly because it is mandatory. It isn't a required component of some entrenched industry dictum. The only possible reason someone would choose Go is because, somehow, it is advantageous to their process. And we've seen an enormous number of success stories with Go recently -- all people choosing to use it for no external reason, but somehow it benefits their project. This is in contrast to, for instance, JavaScript (which debatably has its own merits) where if you want to script on the web client, that's your choice, love it or leave it. In the Go domain, there are countless alternatives.

I find it hard to even express clearly why Go feels so...natural and productive. But it does. And one of those reasons is that the language is so simple and, well, crude, that you don't stop and sit on questions of approach. Somehow it works.

If we need to stick with vehicle analogies, it's more like someone is using a dumptruck to move massive piles of Earth, but complaining that the steering isn't as light as their car.

And FWIW, when people talk about the lack of generics causing them great pain, usually they aren't making a solution, but instead are toying with the language. Doing the typical "make a library that solves all problems" sort of thing. When I am using Go it is almost always for a specific, practical requirement (as duct tape between processes, to orchestrate some high performance C code, etc), and it just...isn't a problem. It really isn't. Unless you're making library code it just isn't this issue it is held to be.


> The only possible reason someone would choose Go is because, somehow, it is advantageous to their process.

Or because of the hype (and that they didn't know any better), which is quite common in the industry nowadays, unfortunately.

In a similar fashion, the Go designers were surprised that, what they thought was a C++ replacement, did not attract C++ programmers.


> People are not being told to use Go grudgingly because it is mandatory. It isn't a required component of some entrenched industry dictum.

You're registering this objection on the basis of JS's privileged status in the browser; I'm invoking it because of The Fine Article's comparison with JS on the server, where it's adopted as voluntarily as any other language -- and where, yes, despite claims that event-driven/callback scattered code are worse than what Go offers, people are able to get things out the door anyway!

And that's true of Node, it's true of PHP, it's true of Java, it's true of most languages people have moved to Go from.

The claim that being able to ship in a language doesn't mean it's wart-free is a pretty solid one, and that's what we're talking about.

> I find it hard to even express clearly why Go feels so...natural and productive. But it does

Does it? I've been working in it for 8 months and... nope. Doesn't feel unusually productive. But I guess your subjective opinion that you can't explain should trump everyone else -- after all, we're using "specious logic!"

> And one of those reasons is that the language is so simple and, well, crude, that you don't stop and sit on questions of approach.

Ah, yes. It's like Java:

"I liked programming in Java mainly because I found it very relaxing. With a bad language, like say Fortran or csh, you struggle to do anything at all, and the language fights with you every step of the way forward. With a good language there is a different kind of struggle, to take advantage of the language's strengths, to get the maximum amount of functionality, and to achieve the clearest possible expression.

Java is neither a good nor a bad language. It is a mediocre language, and there is no struggle. In Haskell or even in Perl you are always worrying about whether you are doing something in the cleanest and the best way. In Java, you can forget about doing it in the cleanest or the best way, because that is impossible. Whatever you do, however hard you try, the code will come out mediocre, verbose, redundant, and bloated, and the only thing you can do is relax and keep turning the crank until the necessary amount of code has come out of the spout."

   http://blog.plover.com/prog/Java.html
(When I started working with Go last May, I had no idea or expectation of the extent to which I'd have thought this article would apply.)

> And FWIW, when people talk about the lack of generics causing them great pain, usually they aren't making a solution, but instead are toying with the language.

Really?

> it just...isn't a problem. It really isn't.

Oh. Sorry, then. I'll just realize that the unpleasantness I've encountered working with it really isn't there, and I'm not focusing on solutions.


You almost sound angry that other people are enjoying and having success with a language that you loath. I would wager that you simply are not taking enough time to shift your thought process to a state that is more in line with what is available in golang.


"and where, yes, despite claims that event-driven/callback scattered code are worse than what Go offers, people are able to get things out the door anyway!"

You misunderstand my argument. If someone is begrudgingly complaining about JavaScript in the browser, well they have a legitimate gripe because they really have no option (beyond various compiles-to-javascript kludges). If those same people used nodejs, on the other hand, which many people do, they clearly found some compelling reason to do so. In the case of node it was that it made code very easily, and by default, asynchronous, instead of the classic .NET/PHP synchronous model. There was a benefit, and people gained from it.

Really?

Why are you using Go? Are you solving a real problem? Did you say "here is my itch, and I am using Go to scratch it?" I have never seen, in these discussions, people solving actual problems complaining about Go. Instead it's the code tourists who want to do some flippant, vaguely directed project and then add "Go Guru" on their resume to give credibility to their complaints.


> You misunderstand my argument.

Apparently. I have no idea why JavaScript's position in the browser is relevant at all to the point that being able to ship in a language isn't evidence that its featureset is ideal.

I do invite you to argue the point further, though. And please continue to ask questions like this again:

"Why are you using Go? Are you solving a real problem?"

Yes, please do imagine out loud that everyone who's critical of Go is just not building real software in it. Hell, follow your "argument" to its natural consequence: anyone not using your personal flavor of Blub is probably just farting around.


Ah, sweet delicious sarcasm. Always the last resort.

There is absolutely nothing drawing anyone who doesn't want to use Go into using it. There are zero external forces or dependencies that are making you build solutions in Go.

So when you come telling a tall tale of your peril with Go, it just stinks. Do you understand? You can, from the outside looking in, have criticisms of the language, but when you try to add authority to your claims by manufacturing great experience, it sounds absurd.

The relevance of JavaScript -- and this really doesn't seem that difficult, though I think you're trying to be difficult -- is that, to reiterate, people have to bear it regardless of their feelings about it, so there are a lot of people who despise JavaScript but ply their trade in it daily. There is zero parallel with Go, where there is absolutely no reason for anyone to ever make use of it if it doesn't offer some significant advantage to their project.


> People are building real, working, successful solutions in Go with rather surprisingly regularity (which, if the comparison needs to be made, they don't seem to be doing with Rust)

I have written hundreds of thousands of lines of Rust code for Servo, the Rust compiler, and other projects. Of course it's a less mature language, but people are building plenty of solutions, including production solutions, in Rust.


<snark> had to be hundreds of thousands because you didn't come out of the gates with a decent design and you had to wing it for the last 6 years </snark>

;)


Two things. First, I think it's more about the initial reaction to Go, from someone coming from Rust (or Java, C#, C++, etc).

But even so, I agree the wheels analogy is too extreme. I'd maybe say that it's like hearing that a car uses two motors instead of a differential -- "weird, I thought we solved that problem a while ago..."


> I've noticed a lot of Rust lovers commenting about how great Rust's type system is. It probably is, but I haven't run into any problems with Go's type system.

I think it depends on the kind of things people write. Most people I see writing Go code seem to be writing programs, a piece of code that performs a specific function for a user. In those cases, you very often know exactly the domain types, and Go's type system is perfectly adequate there.

Other programmers write libraries, functionality that is meant to be used by other programmers to build their code upon. In this case, you rarely know the context in which a user of your library will use it, therefore you cannot really make any decision about types. This is a big reason why people like having parametric polymorphism.

The constant arguments that we see online probably comes from people writing programs and people writing libraries arguing with one another without understanding the context in which the other writes code.


  > Other programmers write libraries, functionality that is meant
  > to be used by other programmers to build their code upon.
  > In this case, you rarely know the context in which a user of
  > your library will use it, therefore you
  > cannot really make any decision about types.
Uh ? Even for a library you certainly can make decisions about types, document them and enforce them. Who wants to accept unspecified data types ?


Literally everyone who's ever written a container.


That doesn't mean no decision has been made: in a typed language with subtyping, this amounts to choose the "top" type of the type hierarchy, and without subtyping, you're choosing not to enforce structural constraints. In untyped languages with structured values (like any usable language), you make those decisions in the way your code checks for this or that value attribute or runtime structure. I guess unspecified and specified as "any" is often the same, but for me the former is a design mistake.


> - Go is a minimal language and has been called boring. [2] I don't claim to be an expert yet, but I don't think I've reached this level of productivity with a language this quickly before.

I was drawn to Go initially because of its promises around concurrency, but this is why I stayed. Within less than a month, I was as productive in Go as I was in Python, despite the fact that I had been programming in Python for several years at that point.

> - I totally agree with the comments on this thread about dependency management. Godep [1] is nice, but it would be great to see a canonical dep management tool for go.

For what it's worth, Docker has more or less replaced this need for me. I know it doesn't actually do "dependency management" in the traditional sense, but by the time that ad-hoc vendoring no longer works, I've found it's already time to start using Docker for deployment for other reasons anyway. At this point, it's just as easy to use Docker to manage the dependencies at the application level while developing as well.


>Within less than a month, I was as productive in Go as I was in Python

That's not really surprising. Go is actually pretty similar to Python in a lot of ways, the most obvious being the set of built-in data structures.


I'm curious, how does Docker help with that ? You still need to include the dependencies somehow, either by vendoring or using something like Gom, or straight go get.


As someone who has recently ventured into the world of Docker, I have been questioning if there is a need for virtualenv anymore, especially in production.


I do believe the need for virtualenv stays, in development as well as in production. Even when using a Docker container, you will still want to pin your dependencies strictly to specific versions and not risk any interference of Python modules that happen to be on the OS. I think it's important to not make assumptions in that area (dependency management) when wanting to create stable software.


Actually languages with stronger/more capable type systems are a feature and like all features they are wanted by some people who find that it makes their life easier.

Not having a strong type system is not a fault per say it's just that I need a strong type system as a feature(indispensable for me).

For me choosing between Go and Rust is mostly because of the type system.

If Go works for you then it's fine. Although if you want to find out how type system can help you, it's a different story.


Most languages have an equivalent of go fmt.

They are just third party tools that aren't integrated into the language. Which for me is perfectly acceptable. There are sometimes legitimate reasons for formatting code different to what the language creators believe.


I used to agree with you more strongly but I think it's easy to forget just how much time and confusion is saved by having a single standard format which anyone can trivially check and apply. It's not just about avoiding unnecessary bike-shed arguments but also things like the cognitive cost of having to dealing with each project / developer's style quirks.

I'm now inclined to believe that a basically free way to avoid bugs and make things like code review easier and more productive is worth the minor cost of people having to break out of old ruts.


Honestly, it's not the 2-4-8 indentation or the placement of braces that gets me when reading code. In Go, my biggest problem is that there are so many x, err := foo(); if err { ... } that I get lost trying to figure what the happy path behavior is.


I'm hoping Go's error handling is improved in 2.0. I understand the objections to Java-style exceptions but I think they underestimated the actual cost of having so much boilerplate clogging up every non-trivial program, not to mention the way it actively encourages people to punt on error checking which is why so many projects are littered with `x, _ := foo()`.

The approach I'd like would be a lightweight assert-style failure mode where the compiler would treat any function which returns an error as being followed an implied `if err != nil { panic("Unhandled error") }` unless the error is checked on the next statement. That'd allow you to handle things which you expect to fail regularly while preventing the litany of bugs in C programs caused by forgetting to check return codes on things which rarely fail.


    > I get lost trying to figure what 
    > the happy path behavior is.
The happy path is idiomatically at indent level 0.


Except when it's

    if x, err := doSomething(); err != nil {
    }


...the happy path there is intend level 0?

    if err := doSomething(); err != nil {
        return fmt.Errorf("something failed: %v", err)
    }
Or,

    x, err := doSomething()
    if err != nil {
        return fmt.Errorf("something failed: %v", err)
    }
    
    log.Print(x)


Again. Third party tools will have exactly the same benefits.

People have been using standard code formatters in Eclipse/IntellIj for what decades now ?


> a single standard format


indeed. Pretty sure there's some cognitive load involved for developers who come onto a team who uses a style that's different to what that developer is used to. Languages with strict style standards remove this problem.


Unless you change the settings it'll default to the Java Conventions.


> Again. Third party tools will have exactly the same benefits.

If that were true, the frictional problems I mentioned would not be the rule in every other language. Even something like Python, where PEP-8 has been recommended strongly by the community for many years and has widely available validators and automatic reformatters, still has perpetual low-level debates about this.

In languages like C, where there are multiple well-established conventions, you can still find bitter arguments going on over things like optional braces because there are still tons of bad programmers out there who think it's preferable to ship massive bugs every few years than type two extra characters.


It always great to have whole files change because your coworker is using a different code formatting template for Java in his eclipse.


>- Go is a minimal language and has been called boring. [2] I don't claim to be an expert yet, but I don't think I've reached this level of productivity with a language this quickly before.

Tried Lua? Your opinion interests me ..


>- In general the document is solid, but I've found the usability of the generated docs to be poor. You think they could bribe a few Google designers to spend some time fixing that...

Please elaborate. What exactly do you mean?


I will give Rust a try when it has a solid library like Go


This is just another generic Go vs Node post. Do we really need another post telling us about Go's concurrency/built-in features/compile benefits.

This post sadly doesn't really go into much details that bowery.io is trying to solve, how Go fits that and why Node was so bad.

A basic crud webapp would probably be better suited towards node and it's larger list of libraries supporting that kind of stuff.

On the other hand, building you own messaging queue or doing heavy mathematical processing might be better suited for Go.


Fwiw, I have been doing a lot of crud work in Gonthe past few months, and haven't found it particularly burdensome. I have to write my own SQL and map it back to structs, but I consider that a good thing. I might have to write about some lessons learned.


Please do. I come from java, and am currently finding Go a bit cumbersome to work with. No Exceptions, lots of nil checks and a poorer ide makes it quite a bit of work. I also find testing a bit harder to do, but it's probably because I'm in a javian mindset.


Do you mind me asking why you chose Go? It sounds like the problems you have would all be solved by using a traditional language with a mature framework or ORM.


Actually, I would like to see a case by case comparison why / how go's concurrency primitives are nicer/better than something equivalent in node.js/javascript.


Not exactly what you're looking for, but it might help: http://notes.ericjiang.com/posts/791


>In Go, you can define different files for different operating systems that implement functionality depending on the operating system.

That sounds like it's actually very difficult to support multiple operating systems. As a developer I never, ever want to write any OS-specific code. Sure, that's sometimes required, but saying that the solution is to have multiple files, each for a single OS, doesn't sound good. It's a lot better to abstract the OS away. Node.js does this quite well. Seemingly a lot better than Go.

Besides, Node.js doesn't need to be compiled for each system. This alone makes Node.js better for writing code for multiple operating systems.

>Go is a compiled language so distributing applications for use on multiple platforms is just easier.

I disagree. You need to compile to code for every single platform, making code distribution costly. With Node.js you can simply distribute the code as it is and it probably works in any platform. (The probability is as high as it is for Go assuming no extra work for a new platform). Sure, each platform needs to have Node.js, but Node.js is supported in most platforms.


> I never, ever want to write any OS-specific code

With Go, you never, ever have to write any OS-specific code. From a single source, you can build executables compiled for different operating systems.

In any case, you're right that it can be nice to simply "run" a JavaScript application directly from its source code without worrying about compilation.

> You need to compile to code for every single platform, making code distribution costly. With Node.js you can simply distribute the code as it is and it probably works in any platform.

You're missing the point about distribution. Let's say you write a non-trivial command line application, and want to distribute it to your clients. With Go, you can distribute your program as a self-contained executable file. Yes, you may generate a few versions (Windows, OS X, etc.) depending on the needs of your clients, but the cost is a few seconds of compile time, and a few seconds posting links to the Windows, OS X, etc. executables. The cost is negligible.

Compare that to Node. How are you going to distribute your Node app to clients? Is every client going to install Node on their personal computer? Will they be able to figure out NPM? Yes, it's easy, but they'll mess it up anyway. What happens when the network has a hiccup and npm doesn't download your dependencies correctly, or they try to upgrade your dependencies and everything breaks?

If you plan on distributing your Node code, you're pretty much limited to distributing it to other Node developers. That's not going to work for everybody.


> With Go, you never, ever have to write any OS-specific code

It actually depends what you want to do. Since Go tends to be low-level, there may be a moment where your code goes into syscall land, in which case you're going to be OS-specific.

The most recent example I have in mind is mmaping a file: see https://github.com/edsrzf/mmap-go: there is a windows- and a unix- specific version. If you're using something else, you're out of luck (with this package at least)

There is a syscall package, but it's just piling up a lot of syscalls with already some OS-specific stuff. It is going to be so much of a burden to manage that the Go team plans to abstract this in a new package (https://golang.org/s/go1.4-syscall)


>With Go, you never, ever have to write any OS-specific code.

Okay. The article claimed otherwise: "In Go, you can define different files for different operating systems that implement functionality depending on the operating system."

>Yes, you may generate a few versions (Windows, OS X, etc.) depending on the needs of your clients, but the cost is a few seconds of compile time, and a few seconds posting links to the Windows, OS X, etc. executables.

Except when the developer only compiles for Windows and Linux, but someone wants to run the code on Mac os X.

>Will they be able to figure out NPM? Yes, it's easy, but they'll mess it up anyway.

You don't need NPM. You can fetch the dependencies and include that with the installer. There's a downside to that, though, which is binary-packages with npm.


> > With Go, you never, ever have to write any OS-specific code.

> Okay. The article claimed otherwise: "In Go, you can define different files for different operating systems that implement functionality depending on the operating system."

Both the article and the poster you're replying to are correct. You almost never have to write OS-specific code, but you can write it if you feel there's a benefit to it. Much like Node doesn't make you write C++ code but allows you to do it when you feel it's necessary. The article's main point was, I'm assuming, alluding to Go's build tags which are much more elegant than the traditional pre-processor directives used in the C/++ world. They give you a powerful expression language for targeting specific runtime environments that lets you separate out your OS-specific code in a very clean way.

When it comes to distributing an application, there's another advantage that Go has over Node. One of the common ways that people are distributing server applications these days is as Docker images. It solves the problem of users needing to understand npm quite nicely for a Node application, but makes the distributable artifact significantly larger since it includes the bulk of an OS alongside the application code. With Go's ability to create a statically-linked binaries, you can build your Docker images "FROM scratch" and images can be as small as 2.5m.


Further to what curun1r said, most(all?) of the Go stdlib is written in Go and that has much platform specific code. Hence, it supports it. However, unless you're writing system code you will most likely never need to touch this.

http://golang.org/src/net/


Obviously you need to write OS specific code, even with node, if you are doing platform specific tasks. Normally you don't need to care.


You don't need to include the binaries, once you can run "npm rebuild" in the installation process.


That's a very naive argument. There are so many other variables in choosing a cross platform language which you've overlooked:

]] Performance (AOT compiled languages will typically out perform JIT compiled language

]] user interface (is this going to be a command line app? Does it need a GUI? And if so, what frameworks are supported and do they need any OS specific boiler plate code?)

]] required runtime environment (does your language tool chains support compiling to a native binary (Windows PE / Linux ELF) or do you need a language runtime environment? And if the latter, what's the likelihood of the target OS having said framework pre-installed?)

I'm not trying to take anything away form Javascript / Node, but it loses as many points as it wins. And frankly both languages fail compared to some other languages too.

Personally I mostly target Linux and FreeBSD, but the majority of my Go tools will compile for Windows with zero code changes (the standard Go libraries actually do abstract away most OS specific discrepancies) and all of my code works on Linux and FreeBSD without any Linux / BSD specific code. So I think the issues of different files for different OSs is overstated anyway.


>Performance

I didn't argue anything about performance. Go might have better performance than Node.js, but that doesn't make Go better for cross-platform distribution! They are separate factors. If performance is your top priority and Go has better performance than Node.js then choose Go while acknowledging that it's possible that Node.js has better cross-platform code distribution support.

>user interface

I didn't make any arguments about that either.

>required runtime environment

Now that's relevant when it comes to cross-platform distribution. Node.js has that covered pretty well.

>I'm not trying to take anything away form Javascript / Node, but it loses as many points as it wins

My comment was not about Node.js vs Go as a whole, it was about developing cross-platform software.

>So I think the issues of different files for different OSs is overstated anyway.

If you look at the core issue here, it's that theoretically speaking "all things equal" Go and Node.js needs about as much work to implement a new feature that works with most platforms. However, on top of that Go requires a compilation step for every supported platform, and that's not required for Node.js.

However, Node.js requires someone to compile the Node.js environment for each supported platform. For most cases that's already done.

This is my core argument that Node.js does cross-platform development better. It's one of the things that Java and C# got right.


"This is my core argument that Node.js does cross-platform development better."

Your argument is theoretical. In practice, people are finding Go apps easier to deploy. Reality trumps theory.

Why is reality trumping theory? With Go you one artifact, the executable, which runs on its own and you're done. With Node, you don't and you're not done, and even with the incredibly minimal bit of Node stuff I've touched (keybase.io, one of the minifiers), I still had to fight with Node to get it to run. Sorry, this one is easy to objectively call: Go produces artifacts that are easier to deploy. It doesn't matter how you try to talk around that fact, it simply is not the case that you ship one file with Node and are done; that is at best the best case when all the stars align and the wind is at your back.


javascript requires you install Node on your target platform alongside your Javascript program, where as Go doesn't. So the extra step you described gets equalled out.

as I said, it's very naive to blanket claim that node is better for cross platform development.

If I'm completely honest, i find people who say languages are definitively better at boardly defined subjects are usually lacking objectivity. Programming can seldom be summarise so easily without losing all precision.


What prevents me from bundling node with the app? That's how NW.js does it. (I hate the 100MB wasted space)


Speaking as someone from a team that bundles a large portion of a (python) runtime with a distributable, this is a BIG BIG BIG pain in the ass.


> That sounds like it's actually very difficult to support multiple operating systems. As a developer I never, ever want to write any OS-specific code.

You may not, but if you want something to work on multiple platforms that someone else has not abstracted, you have to do it anyway. When you do, you may want something more orthogonal than cpp macros.


> Go is a compiled language so distributing applications for use on multiple platforms is just easier.

How is this a true statement? Ease of distribution isn't a function of a language's runtime environment (native vs interpreter).


Presumably he's talking about statically linked binaries.


They just mean static compilation, the program is a single file with all dependencies linked inside it.


Sure it's a true statement. Even if you have to compile to different targets (and you do), that's much simpler than implementing shared dependencies on those different targets. When you deploy a binary with no external dependencies, you can (generally) set it and forget it.

It's not to say there aren't meaningful differences across targets you need to account for, but it is "just easier" in my experience.


So, it's not a function of compiled vs interpreted. It's about a single binary vs shared resources.

So while you can't get a single binary with an interpreted language (you need the shared runtime), however you can also get shared libs using a compiled language.

I've found doing cross platform development using NodeJS significantly easier than using C++ (of course I had to use compilers that didn't default to IEEE 764).

So old.


Minor nit pick, but theses days "interpreted" languages are also compiled. What we are really taking about is AOT vs JIT (though even here, there are AOT compiled languages that still require a supporting run time environment installed, such as Java)


Java's a bit of a special/odd case, since it's AOT-compiled into a bytecode that is then JIT-compiled into native instructions.


Not that unusual these days. CPython supports a similar intermediate binary (.pyo) and .NET does the same too, albeit the bytecode is shipped inside a PE.


And you can't even get that from the language itself. While MRI (last I checked) doesn't support an intermediate file of its bytecode format, Rubinius does (.rbc), for example.


Excelcior JET, Atego, JamaicaVM, RoboVM, ART, CodenameOne, SubstrateVM are just a few of the available native compilers for Java.


> So while you can't get a single binary with an interpreted language (you need the shared runtime)

Offtopic nitpick: of course you can, just combine the runtime with the code and wrap it all in a single executable. E.g. http://www.py2exe.org does exactly this.


For me the single biggest disadvantage of Go against Node.JS is the lack of a decent dependency management solution. NPM is awesome and Go doesn't even have a "meh" answer to that.


I feel and share your pain. I dislike the model of having to vendor in every third party library's source code, so I'm trying to build an alternative tool to Godep[1]. It's still a work in progress but the basic functionality is there :)

[1]: https://github.com/fishworks/dis


What problems have you had managing dependencies with Go? I use Godep to vendor each dependency and rewrite import paths to use the vendored package. I found it to be an easy and effective solution.


NPM is only awesome until you need to do something with it on Windows.


What kind of problems are you having with it? I'm using npm on Windows and it's working out great! I'm actually using it as my build/task runner rather than using bloated grunt or gulp. It's easy to configure and read. I run my linter, unit test, jscs, and bundler all configured in package.json.

I also install git bash and conemu to have bash on Windows which makes things much better. I don't use windows console.


My experience is that Npm "kinda works" on Windows. There are mysterious race-conditions and annoying bugs. And I'm not even talking about npm being technically completely incompatible with Windows due to the 256 character path limitation.


I had a global environment variable conflict because something else was named "node.exe"... =/


It's not just npm. A while back I had to set up a Rails dev environment for a client who used Windows. shudder.


Never had any problem with it when we did a Cordova based application for a customer of ours.


There are quite a few packages in npm that require native compilation of some part of their system during install. These usually fail horribly on windows without spending a lot of time tweaking your system in ways you probably don't want to. This is in sad contrast to how well many of the other libraries just work.

I would have thought it'd be possible to emscripten compile something like tinyC, and make a C compiler you could naturally fit into the node ecosystem to build native libraries.


I see. However that is a common problem in any platform that doesn't follow the UNIX way.

I imagine node.js for IBM i or z/OS to have similar issues.


This is almost certainly true, and if there were as many people trying to use node on those operating systems as there are on windows I expect you would see a similar number of complaints.


Maybe it's just me, but I really like the way Go does package management. Not needing to publish to a central place for packaging is awesome (just have it on any website), but I agree that it needs reorganization (godep is a step in the right direction)


Go does lack quite a bit of the web pizzazz you'd find in rails, but I learned a lot more by writing web things in go than I did in rails because so much less of the magic is hidden away from you.


Go, unlike Rails, is not a web/MVC framework. It's a systems language, which is even still separate and unique from Ruby, a dynamic language. I agree you'll certainly learn more from Go than you would from Rails, but it's helpful to be aware they're very different.

Apart from my own opinion of Rails (I'll pass, thanks), it's also worth considering that Go, again a systems language, may not always be appropriate for typical web development. That's not a rule by any means. Just pick the right tool for the job.


> systems

Here we go.


rimshot


Would you have had the same experience by coding directly in Ruby? The magic of Rails would similarly be hidden from you, forcing you to learn what's going on under the hood.


I'd consider that a feature of Go. At least that this is not your only way.

What you want is maybe something like Beego.

http://beego.me/


I ve given beego a go and although it is closer to a full stack solution to write in golang, I find it lacking still, and I am still looking for someone to share their experience by example moving from NodeJs.


This was something keeping me back from Go before. However, in 2015 when you're doing so much more on the client, and things like Angular and React are available, this concern becomes reduced or eliminated.


Go is a language and Rails is a framework though it's not even an apt comparison. Ruby and Go is a better comparison though still not the best.


You can't really compare Go with Rails...


This is true. They really are apples and oranges; but when life gives you lemons, I choose web frameworks.


For testing frameworks, standard library tasks, workflow: he author prefers less choice and more standardisation, hence Go > Node.js.

Which I find very disappointing. One thing that I learned, if some standardization happen and you have to use it, it will cause you pain eventually.

Obviously, there is honey-moon period and a clear path what to do if you only got "one" standard, but the author will eventually there is no free-lunch. The standard will be insufficient for some his usecases and then what....

Node.js out of the box embraces multiple solutions - I know this can be overwhelming, but it gets better over time not worse. When you know, the trade-offs between the different choices, you feel empowered to pick the best tool / lib for the job.


I have to agree with your sentiment -- certain types of simplicity, though attractive, can be a misleading double edged sword.

I once let a team split in two for a week to separately build the same product using two competing UI frameworks, before our final decision. The simpler, more opinionated framework won, hands down at the end of one week, being far more productive with the least effort. But, over subsequent years, we found the framework far too restrictive, requiring convoluted solutions when problems strayed from the straight and narrow, leaving our code base littered with painful hacks.


I think there's a difference between standards at the language level and standards in library code.

There's also the point of simplicity at which it actually doesn't matter how something is accomplished, only that it is, which is where the Node.js ecosystem falls apart. Too many libraries with half-baked feature sets, each new library built because the developer didn't like the last one.


Go is definitely promising but the last time I checked the problem with web development with Go was that there is no mature libraries for User authentication etc(Please correct me if I'm wrong). This makes going with Node or something like Rails more tempting.


It's as easy to implement authentication in Golang as it is in Rails. There are gaps in the web stack for Golang (databases are particularly painful), but this isn't one of them.


I wrote a Go Web Application with authentication and an API to learn Golang.

I must say, writing an API and some other services (SMTP pipe listener) was much nicer in Go than Authentication.

There is gorilla/sessions for sessions, but there's a lot to be desired here. A weak secret here means other people can decrypt the SessionStore Blob and possibly get secret information as a passive attacker or authenticate as another user. This sessionstore passphrase is the key to your entire webapp.

There's also nothing built in to Go for CSRF tokens, and HTMLTemplates are nice for preventing XSS but a pain in the butt for embedding, generating, and storing/regenerating (depending on how big you are) CSRF tokens.

Overall though....Writing Go has been pure joy for me. These are super knitpicky things to complain about.


I think those issues will improve over time with maturity. Golang seems to not like to do things in more than one way, as the article stated. Currently there is competing solutions to all of those problems[1]. I suspect you won't see built in solutions until community libs and users choose the prevailing standard solution to each problem.

To also be fair, web apps are nodes bread and butter, not so much so for Golang (apart from maybe api's - which tend to have pretty straight forward auth mechanisms and dont require csrf, xss or templating solutions, traditionally anyway). With that in mind I wouldn't be surprised if go's devs continue to leave web solutions up to the community. I expect to see a lot of frameworks come along similar to pythons django, rubys rails, and phps laravel.

Disclaimer: non elitist node dev, closely watching go

[1] https://github.com/golang/go/wiki/Projects


I agree. Go was really nice to write code in since I do a huge variety of system level and Web things. It's my goto for practically everything now.

It will get better but for now I think writing a full web-app in Go, (presentation etc) is pretty annoying.


I don't think you can really beat node for static web-apps.

Its just too strong. The development loop is great when using a build chain like gulp, deployment is relatively easy, scaling up and out is easy (by nature of it being a static webapp), single toolchain, single language (well at its core anyway) etc etc.

Writing API's, specifically restful ones, can be done, and for small stuff its quite nice, but as soon as you start adding processes, services and anything more complex than crud functionality it falls over development wise.


>no mature libraries for User authentication

"User authentication" can mean 1,000 different things, maybe if you clarify your use case, people can suggest solutions.


> "User authentication" can mean 1,000 different things

you mean like 4 different things... and even those have common components


Agree, that was a bit loose. Something like Passport.js(passportjs.org).


Checkout Negroni [1] for middleware configuration combined with restgate [2]

[1] https://github.com/codegangsta/negroni [2] https://github.com/pjebs/restgate


Negroni looks interesting. I saw there is a middleware called permissions2 that have some nice features. Will check that out, thanks!


I wish a language with advanced types like Haskell or OCaml would have the same tooling and ease of distribution around it that Go does. I haven't built anything in Haskell/ML in a while, so if anyone has any updates on this please chime in.


OCaml is usually statically compiled with ocamlopt, so distribution is pretty easy. As long as build/deploy platforms match, then you're good to go. Shared libraries only come into the picture for unusual cases, eg FFI.

OCaml tooling has also gotten a lot better over the past few years, mainly because of OPAM. The library count has exploded, and the language still gets regular point-releases with improvements designed to aid tooling, such as extension points.


The last serious project I tried to do with OCaml (maybe 4 months ago) was impeded by a ton of dependency problems (this library in OPAM says it depends on this other library, but it doesn't compile because the latter has changed; this dependency won't build in OCaml version .X but another one won't build in .X-1) and ecosystem sparseness (two partially-complete, years-old libraries to do the same thing, etc.). I was eventually stopped in my tracks by an impressively opaque camlp4 error.

(My favorite example is when in #ocaml I asked what testing tools people used; the most positive answer was along the lines of "there's OUnit, but I don't know anything about it".)

There seems to be three awkwardly coexisting OCaml communities: the old academic crowd, the Jane Street people, and a crowd of clueless newbies like myself. It's a really great language, but the ecosystem is going through some growing pains right now.


You may wish to explore Rust - http://www.rust-lang.org/. I can't speak to tooling but it has advanced typing and ease of distribution seems similar to Go.

Edit: mea culpa for my attempt at tongue-in-cheek humor, "I think that's called Rust - http://www.rust-lang.org/"


Rust's type system is definitely more robust than Go's, however it's also a different language and different philosophy. Go was created to be easy to read and easy to write, which is mirrored in the language (e.g. no generics). Rust is more complex, which might be a factor when deciding between Go and Rust. Plus it does not have the same adoption in the industry as Go.


No argument here. OP specifically mentioned advanced typing, tooling, and distribution. Rust covers at least two out of the three (can't speak to tooling) so I thought OP might like to explore it a bit.


>I wish a language with advanced types like Haskell or OCaml would have the same tooling and ease of distribution around it that Go does.

I love the philosophy behind Go and enjoy coding in the language, and the tooling is a major part what makes development in Go such a breeze. Go seems to be consistently praised for its tooling and I suspect the developers of other languages are paying attention.

Having said that, I do wish Go 1.4 retained the Vim plugin that was bundled with the earlier distributions. I've had nothing but trouble setting up vim-go and its myriad of dependencies on Windows. The process was so easy before.


OCaml does have opam (package manager), ocp-indent (a code formatting backend), merlin (a code formatting front-end for Emacs, Vim and Acme), a REPL, a byte code compiler, a native code compiler, a debugger that supports stepping backwards, can integrate with gprof, has ocamllex for building scanners, merlin for building LR(1) parsers, etc. And OCaml's been gaining speed in the past years, so there's a lot of nice things to see there.


Yea, I really like GADT too much to give it up. With Swift/Haxe/Rust/Haskell/F# all having them.

You may find this interesting, someone implemented a parsec-like library in Go [1]. I haven't wrapped my head around it completely, but it looks like it's all dynamic [2].

[1] https://godoc.org/github.com/prataprc/goparsec [2] https://github.com/prataprc/goparsec/blob/master/json/json.g...


Are you sure GADTs are possible in Swift and F#? I haven't seen what syntax supports that in those languages. Do you just mean Discriminated Unions (i.e. ADTs). There is a difference between GADT and ADT.


You can use this (https://halcyon.sh) for Haskell. Still not the same though.


So is this is a growing sentiment? Recall that TJ famously left Node.js in favor of Go.

I find Node downright amazing for web development. npm has everything you could ask for. And the whole community takes the unix philosophy and runs with it. Also love that there's no single best way to create something, you as the architect, gets to decide.

And io.js/ecma6 makes node even more appealing.


From what I've heard, TJ is working with Go because Joyent wasn't putting enough effort into releasing features for node and he also got tired of JavaScript callbacks. I think node will see some love very soon, and I know there are plenty of ways to deal with callback hell. That's just one guy's feeling. I really love working with node. But definitely looking forward some new features.


There are lots of reasons! I'd encourage people to try something new (Go, Rust, Scala, whatever), it's easy to ignore Node's shortcomings sometimes. Community was a big one for me, the "unixy" nature of node+npm is no good when the module quality is pretty poor and the names are completely nonsensical, your app just becomes an abstract blob of code that makes no sense. Go's stdlib is pretty rock solid, nothing in Node comes close IMO.


Having just spent more time at work this week creating PR for bugs in npm modules, instead of doing actual work... I'm starting to agree.

But honestly I think that's just par for the course for any substantially popular language. I don't think Go (or any other language) is inherently immune to this.


For sure, there are lots of skillful people working on node as well, I just think the Go team has a lot more experience and it shows.


I disagree with the concurrency part. Node.js has excellent built-in IPC support through the process and child_process objects.

Since Node.js is JavaScript, you can't possibly argue that Go code is more 'portable' than Node.js. For one, JavaScript can run on more machines than any other language.

Go will not run in the browser because most browser vendors will not let that happen. On the other hand, JavaScript is already universally accepted by everyone and it's everywhere - You can run JS in the browser, natively on mobile devices, on the server, on set-top-boxes, on robots/IoT devices and just about everywhere you can imagine. Anybody can implement and modify their own JavaScript engine to suit their specific needs.

No need to worry about protocols - Since JSON is a subset of JavaScript, you can seamlessly pass objects between the client and the server and no need to context switch between programming styles when going between client and server.

People who don't like JavaScript mostly feel that way because they don't understand it well enough (it's a lot more expressive and powerful than people imagine). I have programmed in many different languages - C/C++, C#, Java, ActionScript 3, Python, AVR Assembly (ATMEL ATMEGA8-16PU microcontrollers and family) and a few others but I feel that no other language has the expressiveness and elegance of JS.

Before I got into Node.js, I considered myself 'language agnostic' because I often switched between languages because no one language could do everything I needed. I no longer consider myself an agnostic - In fact, I feel quite comfortable saying that C/C++ and JavaScript are the only two languages worth knowing.

In reality, you can't be 'fluent' in that many languages because fluency requires constant practice - It makes sense to settle on fewer languages - Mastering a language/tool allows you to focus on what's really important - Logic and structure.


They left out the most obvious reason for them to switch. Their business is based on docker, coreOS etc . . . aka the Go ecosystem. In that context developing Go expertise just makes business sense regardless of technical merits.


It is frustrating to see how many Go vs Node posts are happening here. I have been implementing a bluetooth LE module in Go, and due to lack of some robust libraries, had to go back to Node. This is primarily a question of maturity, but I also realised that my use-case didn't really need the thing which Go is most useful for - namely really really good concurrency primitives. I am quite sceptical about Node's future because of that forking fiasco, but at this point in time, both Node and Go provide enough distinct functionality that both will be used for a long time.


I'm primarily a mobile dev, so the biggest impediment to me adopting Go over Node is the fact that converting and manipulating my data models to send as JSON documents is considerably harder on Go - there's no Go equivalent to Gson yet, nor will there likely ever be due to the nature of the language.


Did you get a chance to look into encoding/json package[1]? I come from Java background and have extensively used Gson in projects, I found encoding/json at par with Gson. You can find more examples here[2].

Would you mind if I ask what did you find lacking in Go's json package when compared to Gson?

[1] http://golang.org/pkg/encoding/json/ [2] http://www.attilaolah.eu/2013/11/29/json-decoding-in-go/


That's exactly what he is talking about. In a dynamic language, you just parse the JSON and access the resulting object. In Go, you need to have a matching record or use the interface type and implement a decoder.


Oh, apologies. I thought he is talking about Gson[1], and hence the comment.

1. https://code.google.com/p/google-gson/


I'm having a hard time enjoying Go. It just reminds me a little too much of Java, and I programmed in that language for way too long. After I finished my test program, I uninstalled the toolkit from my system. Right now, I feel that there's no perfect language for me. I do love JavaScript, but there are some things I wish they'd fix. And it takes browser makers way too long to support the latest features. Been messing around with Erlang. Kind of an interesting language.


Maybe you don't like programming? Or you did once, but you've grown bored with it now that it's not as challenging?

In my opinion, a programming language is good if it enables the programmer to move from a concept to correct and maintainable implementation with minimal friction. I don't expect a programming language to entertain me.

The burden is then on me to find projects that I believe in and will enjoy implementing. This is, of course, easier said then done.


No, I actually do like programming. And I agree with you that there's more to choosing a language than having fun with it. I've had to make that decision for 2 decades. :) But my idea of fun is when I find a language that does a lot with less code, easy to apply patterns, doesn't have a lot of boilerplate, doesn't take a lot of tooling, simple, sleek, and allows any style of programming (e.g. oop, functional, procedural). Like I said, I've tried Go and it just didn't feel like that. It felt like, well, Java. The language I used to build apps in the 90s.


Any modern Lisp gets you there. The three leading dialects, namely Common Lisp, Racket, and Clojure, are all excellent. Each makes different trade-offs in what it offers. As a former Java programmer, you will probably like Clojure's near-perfect Java interop and excellent performance. Racket is probably the best batteries-included language and environment available today. Common Lisp is a bit grandfatherly, but it's the kind of grandfather who teaches you to fly his aerobatics plane. Its condition system, in particular, should be required study to anyone who purports to design languages and runtimes.

I read up and played with Rust earlier this week. It's also excellent, and while it's too young and has been too volatile for libraries to solidify, that will change in the next few months. The tooling (as far as Emacs modes and the dependency/build system, Cargo, are concerned) looks solid. Performance is already decent, and has the potential to eventually match C. To be honest, Rust feels like what Go would have been had its authors understood Lisp and Haskell.


You might enjoy Lua (http://www.lua.org/) or k (http://kparc.com/k.txt).


That does sound fun. Let me know if you find it.


"but he didn’t learn his lesson there"

This set me up for a negative article about Go, but, like other Go-related materials, it makes me want to use it. I should use it.


"Something must be done. This is something. Ergo, we must do it."

Why should you use it? What problems does it solve for you?


I for one hail our Go overlords, because that way it will mean less Python, Ruby and Javascript code for serious stuff like backends.. Given the language will please this crowd.

Theres a lot of good stuff, created by good people, in those languages and while the solutions are great, the fact that they are in those languages, make them unfit for a lot of cases.


how is this a useful comment?


It's interesting the switch was prompted very few things that are JS vs Go, perhaps concurrency. The main factors were tooling related, enabling stable workflows and easy deployment.


One thing I hate about JS and the thing I love about Golang: the error handling. I love that there is only one way to do it in Go.

ok, More actually. Some APIs return ok instead of err.


Why on earth would a line editor need platform specific code? Sounds like a case of that's-a-cool-feature-let's-use-it!!!


Golang only 2x ruby at net/http level and same as ruby at web framework level ?

https://news.ycombinator.com/item?id=8964255


On render speed, if you're trying to serialize json 1 million times a second, the benchmark you linked might have some relevance, if not, then you're being misled by looking at benchmarks like that, which measure an app doing not very much millions of times a second, so basically they're stressing the routing path and the json serialisation speed. This is unlikely to be a problem you ever encounter and if you did you'd just rip out the bits you don't need for that path - use static routing, cache json etc, and your speed would be massively improved.

Speed is not the only concern, or even the biggest concern, for most web apps, the constraints nowadays are typically in something like this order:

- Memory - CPU - Bandwidth - Database - Render speed

Clearly that doesn't hold true for all sites, but for most the order is something like that because with caching you can obviate any render speed concerns very easily. On memory and CPU usage, golang completely trounces a solution like Rails (I say this having built similar sites in both) - it's better by a factor of 10, which means you can run a pretty big site with very spartan resources.

The largest obstacles to go replacing languages like ruby as a tool for web apps is more that the libraries at present are not available for everything you might want to do (user auth, sophisticated templating, csrf, fragment caching, form helpers, orms and query builders etc), but that situation is steadily improving, and the standard library is pretty excellent as far as it goes.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: