Hacker News new | past | comments | ask | show | jobs | submit login
The State of Go (golang.org)
466 points by dotmanish on Feb 5, 2017 | hide | past | web | favorite | 388 comments



I don't share some of the opinions I see in the comments here.

I've recently started programming in Go and I am having a blast. Plus, I am making my systems faster and simpler with Go. I love concurrency in Go. I love the concept of Goroutines, the simple and intuitive use of Select. Channels still present a few mysteries here and there... But I'll get it at some point.

But the n#1 thing for me in Go is: It's written in Go. It's refreshing to drill into the language details, I feel like I have learned so much from seeing the Go source code (and having it readily available with a Ctrl+click in VS Code).

Maybe it's because I don't have the "depth" of some of the HN users, but Go feels great to me.


I agree with you, I didn't know how to build a webapp, two years ago, I learned the basics and implemented a fully working webapp in Go along with the REST client, all without having to buy a single book, the docs are amazing, the community is amazing and the language made me build things fast, I love GOPATH, I love gofmt. Apart from the tooling, I felt as if I have been writing Go since a long time, even though I was just a newbie, my app: http://github.com/thewhitetulip/Tasks/

I also wrote a tutorial for newcomers like me: http://github.com/thewhitetulip/web-dev-golang-anti-textbook...


I am really glad for that guide. I came across it last week and really appreciate the methodology (i.e. an anti-textbook) thank you for that.


Thank you for your kind words! I am happy that you like it, I am writing a series of guides on vi, python, git and probably bash along with their YouTube series, you can find them here http://github.com/thewhitetulip/multiversity


  Maybe it's because I don't have the "depth"
  of some of the HN users, but Go feels great to me.
I doubt I have any more depth than you as a programmer, but I've gone one step farther than you down the language safety progression, so maybe my thoughts from here will be interesting.

When I moved from Python to Go not only did my code become more safe, I actually became a better programmer. There are a lot of silly things that you can do in Python that you can justify saying "just this once!" or "it's only temporary!" that are much harder to do with Go. I started writing a lot less complicated functions that did different things with different types, and moved to writing simpler, single purpose functions whenever possible. This was great and I learned a lot.

Then I moved from Go to Haskell, and the same thing happened again.

Haskell makes you specify whether a type can be null or not. It has referential transparency, so you can't mutate variables as a side effect of a function. It has sum types, eg:

  data User = Unauthenticated | Normal UserId | Admin UserId
.. that make it really easy to enforce invariants and are also super convenient to use because of pattern matching. I write a lot less "stringly typed" code now than I did when using Python or Go.

Now there are downsides -- Go has a great standard library, and it's tooling is fantastic (even down to little things like gofmt). I'm not saying you'd have a better experience with Haskell, just that there are real reasons why someone wouldn't want to go back after trying a more featureful language than Go.


> When I moved from Python to Go not only did my code become more safe, I actually became a better programmer.

This is probably more due to the fact that you moved from a dynamically typed language to a statically typed one rather than this new language itself.


But Go really does encourage good practices. I came to Go after programming in C, C++, Java and a bunch of dynamically typed languages. After a couple of years with Go I returned to C (and a bit to Java). And I'm writing better code in those languages now.

Now, part of it is natural progress probably. But especially when I'm writing C, I can tell that I'm writing it much better than before because I'm adopting back some idioms that Go encouraged me to adopt in the first place.

Also, because Go's standard library is so well written, you can learn from the best very easily, and understand what's going on. It's certainly not the case with other languages I write in.


I suspect every time you move to a different language family you learn new things. I did C/C++ and Java then worked with an old Pascal codebase of all things that IMO taught me more than most other languages. Even XSLT taught me quite a bit.


I can't say that Java has improved me in any language, but Go and Python have improved my Java. But any time you learn new idioms in a new language, your understanding of programming gets better I suppose.


Is there a good resource where those good transferable go idioms are written? I dont think I will have time to learn go anytime soon, but would definitely spent time with an article or something like that.


Not that I know of, but Go is super easy to learn. You will get a grip of the basics and be productive over a few hours or weekend at most, and one or two hobby projects later you'll learn to appreciate the stuff I'm talking about.

BTW I've only felt I really knew the language and its inner workings and idioms deeply - after much longer, maybe a year and 2-3 big projects. But you get very productive very fast.


Not only that, but rarely am I supporting a library that I'm the sole developer on. Go takes away so much "individuality" of code. On most teams I've been on with Python and Java I can open up a file and immediate tell who wrote the library based on various style and other such. It's a lot harder with Go and that's a very good thing.


Yeah, at times the obsession of gophers with "idiomatic code" is annoying. But when you read someone else's code and it's idiomatic, you almost immediately have an intuitive sense how it works and can understand and modify it easily. Compared to Java OO code where you have to start chasing inheritance layers to find out where the piece of logic you're actually interested in resides...


Well, "idiomatic code" can often mean "for what you're trying to do, there is a way that works with the language better than any other way; do that". That is, it often means "working with the tool rather than fighting it". So, yeah, do it the idiomatic way unless another way is clearly better. (Idiomatic ought to win if evaluating "better" gives you a tie, because idiomatic will be more readable.)


I never really stopped to think about it until I read your comment, but I just realized the same applies to old Go code. As some of mine is approaching probably close to 2-3 years (and few things I haven't touched or looked at since!), and while it certainly could be rewritten to be better, it's interesting that Go's partial enforcement of idiomatic authorship appears to reduce the number of WTFs generated as a consequence of atrophy over time, to say nothing about how much less time is spent understanding the code.

Perhaps it's psychosomatic, but it sure seems easier to pick up something written in Go--long since forgotten--than it is in other languages. Then again, maybe it's also that Go taught me to substitute cleverness with terseness. The advantage here is that I've never been especially clever.

Interesting!


i think a couple of years of experience and learning a new language .. was a far bigger factor than any intrinsict characteristics of go


Not sure. the diff between 12 to 14 years experience is not like 2 to 4 years.


The type system is an integral part of the language.


That was true until things like optional typing as seen in flowtype/typescript came along.


Not sure why this is being downvoted without comment, considering that it is what accounts for the example that the parent comment chose.


I'm with you. IMHO, Go's simplicity is its biggest virtue. It has fostered a community that values consistency and clarity over syntactic sugar. And, as a result, I find each new codebase extremely accessible.


Definitely. Simplicity, and fantastic standard library. Go is like a much faster and more reliable version of Python.

People comparing it to C++ and Rust miss the point.


Normally it's the other way around, Go gets compared to other "Systems Programming" languages because somehow services got lumped in with that name over the last few years.

To me they're very discrete things, if you can't manually manage memory(raw pointers and the like) then it's not a System Programming language.


Go gets compared to "systems programming" languages because its designers specifically intended it to be used as such [1][2], albeit the definition of 'systems' they are using is deliberately evolved from the original shade of meaning as suggested by low-level languages that are sometimes deemed to be for 'systems programming' to illustrate that the nature of environments has changed, and a new approach is advantageous.

[1] https://talks.golang.org/2012/splash.article [2] https://golang.org/doc/faq


If its a "new environment" doesn't imply that it can't be systems programming?

I totally agree that Go is fantastic for services and networked things.


i.e., distributed systems.


It gets compared with them because that is what it is particularly good for. Arguably, it is much less suited to Type 1 representational systems (http://aryehoffman.com/entry/project-types), for the same reasons as for the C language. Like C, it is particularly suited to Type 2a projects - those in computing and its infrastructure.


> To me they're very discrete things, if you can't manually manage memory(raw pointers and the like) then it's not a System Programming language.

Having a GC doesn't forbid that, in very specific cases.

Mesa/Cedar, Modula-2+, Modula-3, Oberon, Oberon-2, Active Oberon, Component Pascal, System C#, Swift, D are all examples of such languages.


Rust, too, had an optional GC (where the choice is per-data, not global) for a long time and still intended to be a systems language (And was pretty successful at being systemsy IMO). I think there was a time when &-pointers didn't exist and all sharing was done through the GC too. At one point there was a realization that the new borrowing system could be used to write GC-less programs pretty easily, and that was a turning point after which the GC started being phased out in community usage and eventually removed from the language.


I never said anything about having a GC, just that if you can't poke directly at memory when you need to then you're going to have a heck of a time working on the Systems Programming space.


> if you can't poke directly at memory when you need to then you're going to have a heck of a time working on the Systems Programming space

That's possible in go with unsafe.Pointer. Go's runtime, GC and memory allocator are written in Go and make use of this.


Also remember Go was inspired a lot by Oberon-2. The Oberon languages were used for writing operating systems despite a GC. They just used assembly or UNSAFE constructs for stuff the type-safe or GC parts couldn't handle.


As mseepgood already replied, you can do that in Go.


I think you have this backwards. 'Systems programming' has never meant 'operating systems'. To believe that Go is misdescribed as a 'systems programming' language you have to believe Rob Pike doesn't know what 'systems programming' means.


Given Pike's extensive experience inside a world of his own making (Plan 9 and Go), it's entirely reasonable to attribute the misconception that Go is a system language to Pike's idiosyncratic use of the phrase.

If I understand things correctly, Go came about as fallout related to the non-scalability of Python and the massive technical debt associated with Python within Google. The projects to automagically port Python code to Go code are a clear indicator that Go was at least in part imagined as a replacement for Python.

I personally wouldn't describe Python as a systems language, but some might.


Pike's idiosyncratic use of the phrase.

There's nothing idiosyncratic about it. "Systems Programming" has meant a lot more than just "operating systems" for at least as long as I've been doing this stuff, which dates back into the 90's. Maybe in some earlier age it was the case that "Systems Programming" was limited to "operating systems" but if so, it was quite some time ago. Language evolves...


Actually, Go was born out of a desire to make something better than c++ for google scale and style use. https://commandcenter.blogspot.it/2012/06/less-is-exponentia...

It just happens that Go is a better replacement for python than c++ in the general case.


Yeah, one of the cool things about go is it's ability to get reasonable compile times without byzantine management of include files, as in c++. I still don't know of any major c++ code base being targeted by go, whereas python is certainly in the crosshairs.


Perhaps you could help clear up the misconception by fixing Wikipedia's 'System Programming' and 'System Programming Language' entries.

It might also be worth commenting on these[0] Stack Exchange answers, too.

[0] http://softwareengineering.stackexchange.com/q/151610/54726


Wikipedia says:

The primary distinguishing characteristic of systems programming when compared to application programming is that application programming aims to produce software which provides services to the user directly (e.g. word processor), whereas systems programming aims to produce software and software platforms which provide services to other software, are performance constrained, or both https://en.wikipedia.org/wiki/System_programming

By that definition it seems pretty clear that systems programming covers a lot more than just operating systems. But calling a language a systems programming language if it is unsuitable for writing operating systems seems a bit unusual. At least it would have been unusual at the time these terms were originally coined.


Why would I? They support what I said directly - 'system programming' is not limited to operating systems. Here's a bit from one of the Wikipedia entries you mention.

"System software is computer software designed to operate and control the computer hardware, and to provide a platform for running application software. System software is computer software designed to operate and control the computer hardware, and to provide a platform for running application software. System software includes software categories such as operating systems, utility software, device drivers, compilers, and linkers."


"System software includes software categories such as operating systems, utility software, device drivers, compilers, and linkers"

Most of those things can be summed up as "operating systems" (operating system, device drivers, and utility software, e.g. basic backend services) plus some essential supporting stuff (compiler and linker).

So, yeah, it's pretty much constrained to "operating systems" and the few essential items. It's not about network servers the kind Go is used for.


In my experience, pvg is correct. It's been ages since "systems programming" was limited to just "operating systems" from what I can see. I don't know anybody who wouldn't refer to writing middleware or network servers as "systems programming".


So it's not constrained to operating systems but it's pretty much constrained to operating systems. You can see how I'm less than convinced.

It's just not a precisely defined technical term and in a computer language really has more to do with the intent and purpose of the designers and implementors and the operational context than things like 'has manual memory management' or 'must be used for writing an actual operating system'. By your strange definition, writing an NFS server would not be 'systems programming' because for some reason networking is excluded. I don't find this seemingly arbitrary distinction convincing either.


>So it's not constrained to operating systems but it's pretty much constrained to operating systems. You can see how I'm less than convinced.

It's just that operating systems is not just the kernel. The POSIX userland of tools (ls, cat, ps, etc) are also systems programming, and essential part of an OS. And of course device drivers (which they even get linked or loaded directly to the kernel).

Postgres, Varnish, redis, or Apache on the other hand, or some ad-hoc enterprise backend service, is not "systems programming".

>* By your strange definition, writing an NFS server would not be 'systems programming' because for some reason networking is excluded.*

Never said that "networking is exclude". The TCP/IP stack is very much systems programming, as an example. And NFS would be too, as it's still a kind of filesystem (and thus working with the kernel and OS at a low level), and an essential part of a POSIX system.

Some load balancer for MySQL, on the other hand (one of Go's touted examples), not that much.


The definition of 'systems programming' is certainly wooly (and predates all of your examples) but I don't think it's an iterative stochastic hairsplitting fractal, like you're proposing. You've basically argued your way to a corner in which varnish and apache are not 'systems programming'. That's not a sensible use of the term.


If Apache is "systems programming" then why not one of the various web servers written in Lua or Python or whatever?

Are those then "systems programming languages" too?


Nope.


But is the activity of writing a web server in Lua or Python system programming?


Systems are relationships between input from the environment, algorithms/functions to process it, and output to the environment. Basically programs at a high-level representation. Systems analysis, design, and implementation started with basic control systems far as I can tell. At some point, there was a distinction between "systems" and "application" programming made by whoever. Original meaning of the term covered all programming where you then picked tools (eg languages) best suited for particular task.

Go's predecessors... Oberon-2, C, and Limbo... were two languages for OS's plus a distributed, systems language. Go's core is the first two with last being mainly for concurrency IIRC. That with ability to do unsafe stuff makes me think of Go as a systems language used mainly for regular applications.


And further, in my view, if manual memory management is extraordinarily difficult a language is not necessarily a good candidate for systems programming.


You can relatively easily get to manual memory management using Go's runtime, i.e. access those runtime·sysAlloc(), runtime·sysFree() functions directly, the way Go accesses syscalls in the external sys package [1]. It's like ten lines of code, nothing extraordinarily difficult.

[1] https://github.com/golang/sys/blob/master/unix/asm_linux_amd...


The difficulty of manually managing memory isn't necessarily to do with how many lines of code it takes to allocate or deallocate. The difficulty is in managing the scope of the rest of the program that is now susceptible to memory errors, which extends far beyond those initial ten lines of code if encapsulation is done inexpertly.


Yeah i love go and i am a C++ and Fortran dev by day. For me go just gets out of the way, and its just so easy to build actual things quickly. AND you get a static binary out of it which gets rid of the deployment issues with python.


Go is a really good git-r-done tool. There's nothing wrong with that despite what some would have you believe.

Our internal dashboard is Elm but the back end is mostly Go. Both have their pros and cons but both work. That's more than I can say for many other dev tools.


> Maybe it's because I don't have the "depth" of some of the HN users, but Go feels great to me.

I've been writing Go full-time as my primary language for nearly five years. Before that, my languages of choice were Lisp[0] and Python, with R as a very distant third choice[1]. I have always been a polyglot and enjoyed experimenting with any new language I could try out - you'd be hard pressed to name a non-esoteric language that I haven't written more than a "Hello, World" in at some point.

I still write other languages and appreciate them for what they are, but Go is what I reach for when I need to crank something out. The language gets out of my way and doesn't distract me - and as an added bonus, I can be reasonably confident that I can quickly refactor the code 6 months later and still have it run[2]. Go is not a scripting languages, but I sometimes even write small applications in Go that I would have previously written as shell scripts, just because it's easier and less thorny than remembering to avoid all of the pitfalls of shell scripting.

You might say that this is because I've been writing the language for so long - and yes, I'm definitely more comfortable with it today than I was in 2012. But everything I just said was still true even when I was only a few weeks into learning the language. It was like putting on glasses for the first time in my life - yes, I could "see" before, but somehow everything was just a little bit crisper, and I felt incomprehensibly more powerful and capable when writing Go compared to Lisp, Python, Scala, Java, Perl... despite having far more years of experience in those other languages.

If some people don't want to use Go, that's fine with me. But I strongly reject the criticisms that Go is meant for "mediocre" programmers, for programmers without experience in functional languages, or somehow an inferior language because it lacks feature X or Y from language Z.

[0] Common Lisp (via SBCL) or Racket, depending on the project and collaborators

[1] It's a language with a lot of warts, but even Python couldn't touch R for completeness in statistical libraries.

[2] Seriously, I have never found a language that made refactoring as easy - or, dare I say fun? - as Go.


>If some people don't want to use Go, that's fine with me. But I strongly reject the criticisms that Go is meant for "mediocre" programmers, for programmers without experience in functional languages, or somehow an inferior language because it lacks feature X or Y from language Z.

I think such complaints are the predictable backlash that's correlated with the final stage of its hype-cycle. Tech hipsters always need a hot new thing to tout so that they can pretend to know what they're talking about.

Now that we have a new iteration of hyped languages in Swift, TypeScript, and Elixir, Scala, Go, and node.js are on the hipsterdom downtrend (which often also means they're on the mature user uptrend). That prior generation of languages are now at least semi-widely known, so they no longer serve the purposes of the talentless hipsters, who base their self-worth on the esoteric nature of their preferences and need something that most people don't yet know much about to hide their ineptitude.

I think Python is a great example of a community that built a real niche for itself and legitimately earned the respect of mature, senior engineers by repeatedly proving and improving its utility and stability for many years. Giving Go the opportunity to develop this same type of sustainable, consistent, healthily growing ecosystem without a flood of 0.1x programmers and other hipsters is really the best thing for it. I'm optimistic for Go in the long term.


At the beginning of the Java and the XML hype cycles few people called that out the new toys weren't as shiny as they looked on the box. It took 10, maybe 15, years for others to catch up.

Look behind hype cycles and often you'll find $company marketing department.


> But I strongly reject the criticisms that Go is meant for "mediocre" programmers, for programmers without experience in functional languages, ...

It's not a criticism, it's literally how the Go language creators themselves describe it. See the Rob Pike quote at http://nomad.so/2015/03/why-gos-design-is-a-disservice-to-in...


> It's not a criticism

I'm responding to criticisms in this and other HN threads about Go, so yes, I'm talking about a criticism.

> it's literally how the Go language creators themselves describe it. See the Rob Pike quote

Unless you think Rob Pike is saying that Google is hiring mediocre programmers (hint: he's not), that statement is intended as a criticism of academics ("researchers"). He's saying that the same things that excite researchers about programming languages don't lend themselves to good software engineering in industry. (And he's right).

But regardless of what the creators of the language may have intended, I'm saying that the criticism regarding experience with functional languages is flat-out wrong. I've written more code in various functional languages than the overwhelming majority of people who read this site - both on and off the clock - and I'm testifying that yes, even for someone who has deep experience with functional language of both the Lisp and the SML families, Go still has a lot to offer that very few others do.


> Unless you think Rob Pike is saying that Google is hiring mediocre programmers (hint: he's not),

Actually that's exactly what he's saying - although "inexperienced" is probably a better word than mediocre.

Golang is the modern blub language. It's really great for large companies and big code bases used by many people who want to get quickly up to speed. A decent, even new, programmer can get up to speed and be very productive in Golang in a matter of weeks. I can go and read the Kubernetes code base, which is huge, and know exactly what's going on pretty quickly, despite the complexities in that codebase like code generation and massive concurrency.

A language like Rust on the other hand would take months before someone can be seriously productive in it. That has a very real cost. It's sacrificing short term productivity for the long term benefits.

I think for a big company like Google, with so much staff, many inexperienced, and relatively high turnover (lots of people leaving and going constantly), a language like Golang is perfect.

At a small hedge fund, where you have maybe a dozen or two lifers, investing in a more strategic language like Haskell, Rust, OCaml, etc. starts to become viable.


Bah, a language being 'easy to get up to speed with' and 'a perfect fit for large teams working on huge code bases' should be a clue to stay the hell away from it.

Because if Golang maintains its current momentum, someday soon the developing world will start pumping out legions of mediocre Golang coders, just as they did with Java.


OK. I should have said, it's not inherently a criticism, it's just a fact. That others may choose to use it as a criticism--well, that's upto them.

Personally I don't think there's such a thing as a 'mediocre' programmer, I think there are programmers who have studied and trained in concepts, techniques and idioms and those who haven't.

It seems pretty clear from that quote that Google is hiring kids fresh out of college, and instead of training and educating them they're throwing them at an intentionally simplified language to get them to churn out code quickly.

Also I find it hard to believe that type-safety guarantees don't lead to good software engineering in industry, when the biggest industrial users of Python, PHP, JavaScript and Clojure--the dynamic language titans of the tech industry--have all recently developed and popularised type systems for them.

And in fact, I also don't see how you can derive a criticism of academia out of those quotes when they mention 'researchers' only in passing, as a point of comparison to talk about their coders' skill level. Too much mental gymnastics for me.


> I think there are programmers who have studied and trained in concepts, techniques and idioms and those who haven't

Which is really just talking in circles, because as I've now said in three consecutive comments, I have quite extensive experience with functional programming, and so I'm rejecting the argument that Go is simply for people who don't have that experience.

> And in fact, I also don't see how you can derive a criticism of academia out of those quotes when they mention 'researchers' only in passing, as a point of comparison to talk about their coders' skill level.

It's probably because, in five years of writing the language, I've had the opportunity to hear Pike (and others) talk about the topic. So when I'm responding, I'm drawing on that body of knowledge to inform what I'm saying, rather than limiting myself to a single quotation cited on a blog post written by someone who (by his own admission) is very new to the language.


> ... I'm rejecting the argument that Go is simply for people who don't have that experience.

You may reject it, but the fact remains that that was explicitly one of their design goals when creating Go.

> ... a single quotation cited on a blog post written by someone who (by his own admission) is very new to the language.

A quotation is a quotation; either Rob Pike said those words or he didn't. Who cited the quotation doesn't make a difference.


> Unless you think Rob Pike is saying that Google is hiring mediocre programmers (hint: he's not), that statement is intended as a criticism of academics ("researchers"). He's saying that the same things that excite researchers about programming languages don't lend themselves to good software engineering in industry. (And he's right).

If that was the case, it was a very dubious thought. Before Go was launched, the languages used in Google were Java, Python and C++. None of them look academic, none of them seem to require another language that is specifically designed to "unexcite" newcomers. Neither is functional, really.


> Seriously, I have never found a language that made refactoring as easy - or, dare I say fun? - as Go.

Sounds like someone's ready for Haskell.


>I strongly reject the criticisms that Go is meant for "mediocre" programmers

I don't know how else to describe people who don't resent being second-class citizens under the library designers, who don't insist on being able to create their own abstractions and use them with the operators that slices or maps support. The language has extensible interfaces but doesn't use them for things like iteration and equality.


> I don't know how else to describe people who don't resent being second-class citizens under the library designers...

One suggestion: describe them as "people who have a different opinion than I do", rather than automatically concluding that anyone who doesn't feel the same way as you do about something must be "mediocre". There are popular languages that I can't stand writing, and languages that I think are badly designed, but I would never be tempted to say that those languages are "for mediocre programmers" just because they don't have the attributes that I look for.

As a polyglot, I can definitively say that every language in widespread use is "missing" something in its design that, at first glance, would be glaringly obvious to someone who's used to a different language. If anything, the sign of a good programmer (as opposed to a mediocre one) is the ability to conceptualize why a language might be successful despite (or even because of) this apparent "flaw".


"How do I iterate over a slice?"

"for...range."

"How do I iterate over my own type?"

"The hard way."

"What interface can I implement to make for...range work?"

"You can't. Our types are important enough to support properly, yours aren't."

As a programmer I expect more than that, and I don't respect people who meekly agree that creating types is properly left to their betters.


>One suggestion: describe them as "people who have a different opinion than I do"

Some "different opinions" are just different opinions, other "different opinions" do indeed point to mediocre programmers.

I'm not saying that is the case with Go: just that what you wrote is orthogonal. One can have a different opinion that is NOT to be respected, but dismissed. Not everything is equally valid.


Especially when compared to working with something like Spring Boot every day it's fantastic. Getting rid of all the bloat is a bigger win than any of its unique features in my opinion.


I love spring boot. And I like golang as well.

Spring might look bloat in the start, but it's powerful. At present there's no framework in golang which has so much power and freedom...


What are your problems with spring boot? What bloat are you referring to?


I suppose most of my negative experiences with it are specifically in the context of using it to build microservices. The memory usage alone created a bit of a problem, I ended up using nearly all of my 16GB of RAM when I had to run many services simultaneously. And because the functionality of any given service was fairly minimal, there really wasn't a need for a framework like that.

The autoconfiguratuon was also a bit dangerous. Since any dependency could cause any other dependency to reconfigure itself, it made it difficult to determine why things would break at times. At one point one of our libraries that used RabbitMQ behaved differently in some other services because another dependency saw RabbitMQ on the class path and started trying to use queues that didn't exist. Someone spent a day and a half figuring that out because the error was being swallowed by something else so the application was just failing to start with some crypic error. And when autoconfiguration wasn't enough, you'd sometimes find yourself needing to write dozens of lines of Java to do something as simple as connecting to a second database.

In general I found we tended to have less predictable or obvious behavior in our Spring apps, and they tended to be more likely to fail at runtime than I would've liked.


I usually get rid of @EnableAutoConfiguration and then selectively import the auto-configuration classes I actually want with @ImportAutoConfiguration.


A Spring developer once mentioned, on a mailing list post i have long since lost, that the autoconfiguration stuff is pretty much demo-ware. It's good for getting a simple app up and running fast, but for anything serious, you should import the configurations manually, exactly as you say. Fortunately, that's an easy enough transition to make at any point in a project's lifetime.


I don't think I'll be working with it again in the near future but I'll definitely have to keep that in mind in the future.


For me, I imagine the dropwizard guys sat round asking each other what the best servlet container is, web MVC tool, ORM, DI framework, etc, etc. and they choose the very best they can think of for a dev to work with.

Then a couple of years later that company comes along where they ask the same questions and but there's a guy with Tourette's in the corner and Every. Single. Time. the answer to the question is SPRING!! SPRING!! SPRING'S THE RIGHT ANSWER!! SPRING!

From the moment you boot spring boot and discover how much longer it takes to boot it's a struggle not to question the motivations of a place where the answer's the same no matter the question.

Sorry. I know some people love it!


Actually, in that company, the answer isn't always Spring Boot. Sometimes it's Cloud Foundry.


Comparing Go directly to Spring Boot? ;)


I completely agree. Go made me enjoy programming again.


I really enjoy programming in golang, having recently taught quite a few people the language I am forever thankful for its simplicity.

This paired with vscode + click to see other peoples code is a great platform to get started with systems programming and tools development.

Can't thank the go developers enough.


I also enjoy it, but just wanted to note that Go is not really a systems programming language, unless you mean "cloud/network systems".


Yeah, systems programming != distributed systems. I think Rust is a better example of a modern "systems" language.


I don't know. I feel like if I need something productive, I would go very high level like Python. In the VERY rare case Python is too slow, I would go really low level like rust.

I don't see the interest for something that not really low level, but not realy high level either like Go. If concurrency is the main issue and is the niche I'm targeting, I would go Erlang or Elixir.

I have a hard time finding any use case for Go.


For me Go is the goto language for usecases where Python and Java were used. Python is great for tooling, and Java was the primary language for the backend.

So now, whenever i think about tooling or backend, Go is the primary answer, because its good in both paradigms.

The other languages i use is C++, and Swift, each one with their own niches. C++ for complex machinery, that requires more control and integration with other libs, and Swift for general applications, specially the ones that are user focused.

In my case, i cant find a niche for Rust. And thats because C++ is already covering that ground for me. I can see why i would use Rust instead of C++, but in the majority of cases where i use C++, there are huge complementary source code already in C++, making the effort to code everything in Rust from scratch, a complete nonsense.

So for me the language in "limbo" right now is Rust. (and i dont think that people with big C++ codebases would rewrite in Rust, because there's little advantage, at least compared to modern C++)


One nice thing about the "rewrite C++ in Rust" is that oh can do it incrementally; we're taking the same approach for Firefox, for example.

Out of curiosity, what are the libraries in C++ that you miss in Rust, or would have to re-write?


For me C++ (or Rust) would be the languages to go for Browsers, VM's, Compilers, Game Engines, Glue Code for a OS(platform layer to prepare things for a app to run) etc..

The problem is, there's a lot of code in C++ already for all of this. V8, Dart, Java Vm's in C++, Webkit, Chrome, Firefox in C++, great game engines in C++.

Is not that i wouldnt use Rust.. on the contrary. But the problem is, for the usecase i think Rust would be very good, there are a lot of code in C++ already, that would require a effort of years to port in Rust.

For instance i work in Chrome C++ source a lot.. and the codebase is a beast.

Maybe if, in the future, things that are starting now in Rust, will be the the successful cases for this kind of machinery.

But given that, at least i, wouldnt use Rust to make a webserver backend (the same way i wouldnt use C++ for that), because i think its overkill. While i like Rust, i cant see a opportunity to use it, and the great impediment for that, is the C++ codebase legacy, and both languages basically competing for the same paradigm.

But theres a great thing in favor of Rust, because its the only modern real contender to C++. But i think it will be a slow and harsh competition (albeit a necessary one).


Cool, totally get this argument. I was mostly curious if you were thinking about something in Rust, but then found the libraries lacking, as we're trying to work on filling in gaps here.


Yes. And just to make it clear, when i say "in limbo" is actually a compliment, in a sense that i want to use it, but didnt found the right opportunity to do so.

I would be glad to be able to use Go, Swift and Rust, instead of Go, Swift and C++. Its just that i cant find a way to do so, and it has nothing to do with Rust the language, the ecosystem and the community. They are all awesome.


The target audience is people who don't know Elixir and Rust, have no time and not enough conceptual base to learn them in a reasonable time, and have to ship concurrent code, fast. Go is stupidly simple; this can also be an upside.

Python's concurrency story is much better in 3.5+ than in 2.x, but a lot of people use 2.x for various reasons.


Turns out also that, from an organizational perspective, it can take a lot to support n+1 programming languages. A codebase with 10 languages is more difficult to maintain than one with 2 or 3.

As a result I think there is large benefit to having a language like Go -- it satisfies many overlapping needs, and organizations can avoid adopting too many other languages that fulfill niche areas.

At Google there are only (5) core / officially supported languages: Python, Javascript, Java, C++, and Go.

Python is generally applied in a scripting context. Javascript in frontend context. Java / C++ where you'd expect. Go for writing servers, application infra, tools, scripts, etc.


You forgot Dart and Typescript, which power AdWords and Angular respectively.


Same here! I code Go for ~3 years in my spare time and PHP only for hard bucks


> and having it readily available with a Ctrl+click in VS Code

I haven't used VS Code since the beta, but it can do that now? Wow. I should give it a try.


Given some of the comments, I'll make the same comment I've made before: Stroustrup is right, there are languages that people complain about, and languages that no-one uses. Go is now firmly in the former camp.

I'm a C++ dev, and I really enjoy using Go. If you don't like what it does or how it does it, it's not for you. Either way, people are out there using it, making systems from it, and generally getting on with it.


Idk if that's such a clean binary, one of my favorite languages is Haskell, and people both complain about that and don't use it :)


I'm starting a backend job tomorrow that's all Haskell. what are people's complaints?


The main one I see is that it is too hard for programmers who don't fully understand haskell/functional programming.

I see people complain at times about it's performance but there is always someone there to rebut that it's fast at some things but not others.


yea compile times are killing my ability to iterate.


Imagine I gave you reddit gold


> Stroustrup is right, there are languages that people complain about, and languages that no-one uses.

This quote has always struck me as an intellectually lazy cop out to avoid engaging with criticism. It's an indirect appeal to the fallacy of false equivalence: "If people actually used language $Foo, surely they would complain about it just as much, because all programming languages are basically the same."

> Either way, people are out there using it, making systems from it, and generally getting on with it.

See, this argument could be used to dismiss any criticism of just about anything.


To me that quote says that there's no such thing as a perfect language.

Different tools for different jobs. If you wander too far from the main domain of the language, you'll find quirks and it's maybe better to use something else.


Go's success is attributable to the fact that it is the first compiled language in a long time which is backed by a major company and has managed to deliver a simple and enriched experience compared to the old company backed compiled languages.

1. Fast compilation is a killer feature.

2. Ease of deployment, as a self contained executable (static linked), is a joy.

3. Channels are a revolutionary concept to every programmer who had only touched mainstay languages.

4. Type inference is a revolutionary concept to every programmer who had only touched mainstay languages.

5. Go's syntax is less verbose than all other earlier mainstay languages. Such as how public/private is handled through casing, and not having to type public or private.

6. Go's structural typing is a revolutionary concept to every programmer who had only touched mainstay languages.

7. Everything that's new in Go to a programmer who had only touched mainstay languages before it is not there in Go as an extra set of features, but the only thing for them to use. This greatly focuses them on learning those new features. Also, non of the features are too radical to throw them off completely.

8. All the tools for Go, are built by the team behind Go.

9. Go's battery included, and has a great selection of modern standard libs.

When compared to Java, Go lacks very little, and brings a lot to the table. Generics are probably the biggest omission, but that's probably going to make it in the language eventually.


The best summary I read recently is that go isn't a bad language, nor is it a particularly good one. What fascinates me is the way the Golang community have concretised that essential middle-of-the-roadness as the language's prime virtue. That, of course, has long been Java's prime virtue as well. (see Blub Paradox)

By putting "we're okay with being okay" as your Big Thing you're clearly pitching for that vast bulk of mid-quality developers that make up the huge middle chunk of corporate devs, the space where Java reigns supreme.


Nah. I like Go because the language itself is minimal yet powerful, and because the quality of engineering is extremely high. I am so tired of having to deal with bullshit because of poorly-thought-out and poorly-engineered tools; Go minimizes that.

An excellent example is the handling of this bug report(§):

https://github.com/golang/go/issues/12914

which resulted in this language-change proposal:

https://github.com/golang/proposal/blob/master/design/12914-...

And then these commits:

https://go-review.googlesource.com/#/c/36255/

I feel like any other language I've used would've just added a "monotonicTime" function and called it a day; the Go solution is impressive, elegant, and shows an exceedingly high level of care for the end-outcome results for the users of the language.

To me, that's what makes Go special.

(§After a rocky start; it took the core devs a bit to realize it was a real issue because within Google's special environment it isn't.)


I dunno... in some ways, the problem is that they didn't think it through to begin with, and chose something widely-known-to-be-ambiguous-and-problematic like "time.Now()", instead of choosing unambiguous names / structures from the start.

It's kinda the equivalent of making a new language (nowadays) and not defining what encoding your native strings use. Of course it's going to cause problems. Except the timer issue has been around much longer than the standardization on utf-8.


Fair point! And I certainly don't claim that the Go devs don't make mistakes. They started with the theory that the problem should solved as Google does, by arranging that clocks don't run backwards. When it become clear that wasn't reasonable, they moved towards a new solution in a way that I felt was impressive.


It's mostly-impressively backwards compatible, I'll definitely agree there. It's clever, and in many cases it'll do the right thing automatically. Since it seems that's their goal, they achieved it quite elegantly, and that's a tricky thing to do. (edit: and quite quickly! seriously, this is an example of a healthy community at its best)

But personally I don't agree with the decision - it adds surprises when you try to convert times to other types and then compare things. Or convert to something else and then back to a time instance. I've watched things like this become the source of bugs many, many times - this will only make that worse, since now a "time" is two values but you can really only access one of them (the one that's equivalent to wall-clock, which is causing the problems). And they're particularly painful bugs, because the cause lies in implicit conversions and behavior. That seems to run counter to the "minimal surprises" that Go seems to prioritize.


There's no denying it's at least flirting with "too clever" territory. What saves it for me is (1) the analysis of a large body of code that seemed to show only positive impact (2) that the behavior is well-documented and (3) anytime you're converting between types, you should always be thinking, "what is the range of these types? what information might get lost?", which with (2), should leave you alright.

But, I could easily see looking back in 2 years and realizing you were right.


"Should", definitely :) Easier said than done. But I'm happy to wait and see, it's not like this would make Go the only language with weird time handling. As it stands they're probably in a better place than most people are used to.

That code-corpus-analysis is pretty neat, I hadn't looked through in detail before. Thanks for pointing it out!

---

Sorta as an aside, it seems the proposal can lead to:

  t1 = time.Now()
  ...
  t2 = time.Now()
  diff = t2.Sub(t1)
  t1.Add(diff) != t2
Times are hard :|


I think that should be fine.

    t1.Add(diff).Equal(t2) 
would still hold, because Now gets monontonic time, Add and Sub maintain it, and Equal checks it.


It's entirely possible I'm wrong since I didn't read through things in great detail, but this is what I'm thinking.

  // time = [wall, mono], just ints for simplicity
  t1 = time.Now() = [10, 10]
  t2 = time.Now() = [19, 20]             // wall clock lags slightly on second measure
  diff = t2.Sub(t1) = (20 - 10) == 10    // Sub only operates on mono-time
  t1.Add(diff) == [20, 20]               // Add adds `diff` to both wall and mono
  [20, 20] ==?== [19, 20]
I'd expect those to be different, since they represent different wall-clock times.


If both times have mono time, then Equal() compares that, and ignores wall time.

So t2.Equal(t1) is true.

You are right that "t1 == t2" (comparing the raw bytes of the time structures) is false, but that was already broken anyway (because time-zones break raw byte equality).

(Whether you think it's OK to have a language that doesn't overload == and makes you know that for complex structures you've got to call a method like Equal() probably correlates pretty highly with your opinion of Go.)

There will of course be other weird things, like:

    print(t1) // "20 [20]"
    print(t2) // "19 [20]"
But you could argue that's basically the least-surprising possible result in the face of the surprising fact time having gone backwards one second. :)

By the way, worth mentioning that while this is all implemented in HEAD in Go, it's not a done deal yet -- it'll have a 3-month window for people to try it out in the real world, and if it's found to be problematic, it'll get backed out before becoming part of the official release.


>If both times have mono time, then Equal() compares that, and ignores wall time.

Gotcha, I missed that somewhere. That's essentially fine - then the only real surprises are when you deserialize a Time (so it doesn't have a mono time), which should in principle have no interactions with this proposal.

And yeah, Equal vs ==, the meaning was clear enough that I didn't bother to be specific :) Thanks for the infos!


Cheers!


I am so tired of having to deal with bullshit because of poorly-thought-out and poorly-engineered tools

Seems to be some cognitive dissonance (in the modern erroneous sense of the word) going on. This was a hack necessary because the design of the library wasn't fully thought out. Imagining the world would one day become Google is not thinking things out.


It was something not in the library because it wasn't in their sphere of consideration. When that expanded, due to feedback from the outside world, they responded in an impressive way.

And that's just an example that was intended to illustrative.

You'll just have to take my word for it that my experience of the Go ecosystem, tools, and standard library has been more solid than the various other things I've used over the years (python, C# + unity, c++, fucking maven, boost...).

If I'm missing out on something even better, let me know. ;-)


> This was a hack necessary because the design of the library wasn't fully thought out.

Easy to say 'not fully thought out'. It took Java from version 1.2 to 1.8 to fix its date/time library.


  It took Java from version 1.2 to 1.8 to fix
  its date/time library.
That is incorrect[0]. When spreading FUD[1], expect assertions such as these to be fact checked by others.

0 - http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22joda-time...

1 - https://en.wikipedia.org/wiki/Fear,_uncertainty_and_doubt


Clever? Sure.

Elegant? Hell, no. It's an ugly hack.


What on earth is a "good" language?

> you're clearly pitching for that vast bulk of mid-quality developers that make up the huge middle chunk of corporate devs

That was actually something Google aimed for with Go, and I don't see what is shameful about it. It's a simple language on purpose. It is meant to be easily learned by any developer, and similarly Go code is meant to be easily read.

Also, what sets Go apart for me, in addition to this simplicity, is the tooling and documentation. I think people mistakenly yearn for languages that are exciting to use or offer interesting abstractions. This stuff is fun for the individual developer but costs an organization in the long run.

Go is bland on purpose. Notice how between versions most of the headline updates are internal improvements (GC, tooling, general performance)


When I think about Go in comparison to other languages, I think of car metaphors. Lots of people talk about cars that are good. Some people think a good car is fast, some people think a good car is low maintenance, some people think a good car is eye-catching. They are all right, those are all descriptors of good cars.

Go, however, is like a Toyota Corolla or a Honda Civic. It's dependable, but relatively plain. It's not necessarily a joy to drive but there's not much of a learning curve. It lets you go fast, but not so fast you'd hurt yourself. It's designed with safety in mind, so much so that it can feel a little over-bearing at times.

It's not a language that draws you in with one clear feature or philosophy. I've used it very successfully and I still find myself rolling my eyes at "go-isms." Lines of "ok, err = ...", rewriting extremely similar data structures, careful channel management, etc. In a list of dependencies, the go dependency will need the least maintenance time and tuning, but what you do need will often be drudgery.

Go is a useful language, but it's a language that has purposefully stripped out all the magic. People like magic, they miss it.


> Go is a useful language, but it's a language that has purposefully stripped out all the magic. People like magic, they miss it.

I agree with everything you wrote except this. After 3 years in a job where I had to use Ruby on Rails, I am utterly tired of "magic" and I regret the many hours of my life I have wasted debugging issues that were created/concealed by it. Lack of magic is a feature in my opinion. But as you said, that's all this is - opinions.


I find Forth, Ruby, Elixir, various Lisps, etc. almost impossible to reason about because of this. Powerful metaprogramming tools can lead to really hard to understand and hard to refactor code.


>>Powerful metaprogramming tools can lead to really hard to understand and hard to refactor code.

They can, but that doesn't necessarily mean they do.

For example, the usage of Elixir macros, which are the primary metaprogramming tool in Elixir, is discouraged in the docs:

http://elixir-lang.org/getting-started/meta/macros.html#fore...


Refactoring is the worst part, so bad that people just don't do it. This naturally leads to very convoluted code bases. Ugh. Never again.

And actually, this is another place Go shines. Refactoring Go code is easy because the compiler helps you along. There's even standard tooling that automates some of it. Amazing.


>Go is a useful language, but it's a language that has purposefully stripped out all the magic. People like magic, they miss it.

Agreed, and I'd further argue:

1) most people driving Ferraris aren't skilled enough to drive them properly

2) most people driving Ferraris have no need to corner at 120 MPH

3) most people driving Ferraris are just trying to show off

4) most people driving Ferraris are more likely to hurt themselves and others than to save the day through the car's performance and handling

(To be clear: I think we're in agreement, but the metaphor is worth explaining in depth)


It's an apt metaphor. Much like programming, there are a hell of a lot of people driving who really shouldn't be.


Then there should be programming licenses:

Level 1: let interns use Go(-karts), like their parents did with Basic.

Level 2: most languages. Proper training required and you still have to be careful.

Level 3: C, C++, critical code, kernels, crypto code. Training a commercial airline pilot takes years; and while this stuff is not hip enough for some, there's plenty of demand.


C programmers should be held personally accountable for the damage they cause.

Now of course everybody makes mistakes, but if you deliberately choose C when there are better options available then you should pay out of pocket for your buffer overflows and 0-day exploits.


Yes, I think there are a lot of parallels between high performance cars and high performance languages. Both are held in high esteem and are frequently mis-used when a more balanced vehicle would do better.


> It's not necessarily a joy to drive

Go is the most fun language I've been using. On the contrary, I don't understand how some people can enjoy Java.


The thing that makes java pleasant is large open source ecosystem around it + IDE quality (meaning mostly refactoring and code navigation, especially when compared to dynamic languages). Frameworks like spring or hibernate etc are mature enough and old enough, so there is a lot to learn just by reading.

The language itself makes it easier to figure out what large code written by somebody else was mean to do - not that everything would be readable nor anything like that, but easier then say ruby or javascript.


> Go, however, is like a Toyota Corolla or a Honda Civic.

The only problem with this argument is that everywhere - even in this thread - there are people saying that Go is a joy to program in. It's not lacking magic, it's magical in its own right.

A better car analogy would be that Go is a Lotus Elise. It's nowhere near as powerful as your friend C++'s Mustang or Rusty's McLaren. But to C++ and Rusty's dismay Go's little Elise still gets around a racetrack crazy fast. It may have a smaller engine but it's just taken a really different approach to going fast which works really well. And Go has a much more pleasant time getting to his destination than C++ and Rusty do.


>>>> Go, however, is like a Toyota Corolla or a Honda Civic.

>>The only problem with this argument is that everywhere - even in this thread - there are people saying that Go is a joy to program in.

Not sure why it's a "problem". I love driving my 2004 Honda Civic, and prefer it to newer, fancier cars. It's fuel-efficient, drives very well, and has not given me an ounce of trouble. So yeah, the comparison to Go seems very apt.


Some people find dull cars a joy to drive.


Using a similar metaphor, I'd compare Go with a jet that's high performance but easy to fly - i.e. it doesn't have the numerous gotchas and quirks high performance jets usually have that the pilot has always have to keep in mind to avoid shooting themselves in the foot (aka making a hole in the ground :)).

E.g. it won't let you overload your engine by using a very special feature that lets you get away with it, but it'll let you fly fast and enjoy afterwards how trouble free the experience was.

OK, I think I'll stop with the mataphors now :)



> What on earth is a "good" language?

I've seen enough languages to make comparisons.

Some languages get in my way and slow me down as a developer. For example I'll always pick Ruby over Java if I have to deliver something quickly. However some languages get in the way of the CPU and slow it down and if that's important I'll pick Java over Ruby.

So both Ruby and Java can be good or bad languages depending on the use case. Some languages make both the developer and the CPU lose time so I won't say they are good.

I have no first hand knowledge of Go but it seems it's fast so it should be good at least where the CPU matters.


Do you have an example of the community celebrating mediocrity?

My impression is of a community willing to go without some features, in order to preserve those it values. Namely simplicity, explicitness, terseness, and consistency.


Explicitness and terseness seem a bit at odds - I wouldn't call go code very terse at all. It seems verbose and repetitive. Consistency? Aren't only some built in types blessed with generic functions?

Mediocrity? The preference for writing loops over simple maps or folds is a bit mediocre. IIRC in Tim Sweeny's "Next Mainstream Programming Language"[1], he notes that around 90% of all the loops in Unreal are folds or maps. Maps and folds are just simpler than loops, without even appealing to terseness and elegance.

Hey I know I'm in no place to judge -- the creators of go and Google overall have accomplished more than I'll ever do. I just really cannot grasp the mindset and penchant for unexpressive languages.

1: http://lambda-the-ultimate.org/node/1277


Thats not a strength of Go. Structural interfaces, channels and performant M:N green threads are its main strengths, and AFAIK there is no other language that provides a similar combination in a familiar C/ALGOL-like packaging.

If such a language existed and had generics and Swift or Rust style error handling as well as some backing by a large-ish corporation / organization, I think that language would be preferred to Go.

More expresiveness isn't always better. Examples that hit the sweet spot are C# / Swift (C# really needs algebraic data types). Beyond a certain point, you will start to lose users. Haskell is very expressive, but few will ever have the time or patience to learn enough to build their perfect monad transformer stack and take advantage of the mtl typeclasses to easily use it. Even though it does have M:N green threads, channels, STM and everything.

In fact, Haskell could probably compensate for this and beat Go by having excellent library documentation and well written, focused tutorials for the working engineer.


I feel like maybe 10 years ago no one would utter something like "C# needs ADTs" because they didn't have mainstream appeal, despite computer scientists' understanding of them.


Yes, things are moving forward, even if slowly :)


The loop and map are equally readable, it is just that some people are used to one form more then the other.

More importantly, how many character needs to be used for simple idiom like that has zero influence on how maintainable your system is going to be few months later on, how fast it is and so on. The difference between loop and map wont make you do less or more bugs. It may make you read the code few seconds longer first time you encounter form you are less used to - but then you will adjust and read it just fine.


Functions are trivially composable, while imperative loops are not. The difference that makes in terms of maintainability and readability of non-trivial applications is hard to overstate.

Writing code in terms of small, composable, reusable functions with a clear single intent (through good naming), that you can then mix, match, and reuse to compose into larger functions is what makes good functional code so much easier to write, test, and reason about than imperative code.

My favorite intro to functional programming concepts for those used to imperative coding is Sott Sauyet's Functional Programming presentation: http://scott.sauyet.com/Javascript/Talk/FunctionalProgrammin...

The presentation makes heavy use of JavaScript and the RamdaJS library in its examples, but the concepts are universally applicable to any language with the necessary functional programming primitives. It also does a great job of comparing imperative and OO implementations of a solution to a problem vs the functional implementation. I highly recommend taking a look if you're even slightly interested in why so many people are starting join the functional programming bandwagon.

So what I'm trying to say is, it's not just a matter of readability. Although if anyone still wants to argue that imperative looping is anywhere close in readability compared to functional composition for non-trivial cases (think multi-level nested loops vs composing multiple functions), then we should just agree to disagree since I don't foresee that becoming a productive discussion.


"Writing code in terms of small, composable, reusable functions with a clear single intent (through good naming), that you can then mix, match, and reuse to compose into larger functions is what makes good functional code so much easier to write, test, and reason about than imperative code."

Absolute, that holds for non functional code as well.

It just does not matter whether the smallest function inside that system of functions has a loop or a map inside it. Loops are as easy to tuck into reusable functions as maps or anything else. Notably examples in the presentation you link have functional version shorter, but harder to read - they have more features however. Even the first one pipe(..., reduce(add, 0)) just does not read fluently.

But again, this low level has very little influence on maintainability of the larger program. In anything that is not computational library, how you compose them matters more. It is as if you assumed code with loops can not be split into smaller composable units.

I worked with codebase written in largely functional style. It was hard to read at first, but then I got used to it. However, it never became all that much easier to read them loops nor easier to work with. It gets bad when people get clever with composing functions.


> It just does not matter whether the smallest function inside that system of functions has a loop or a map inside it. Loops are as easy to tuck into reusable functions as maps or anything else.

This is certainly true! You can definitely wrap all your loops in functions that take in a collection as argument, and return another collection or value, and as long as you don't produce any externally observable side effects with your loops, these functions are as good as any other as building blocks of a functional program.

Consider the age old adage: "If a tree falls in the forest and nobody hears it, did it actually fall?", similarly, "If a function mutates some internal state only visible within its own scope (a counter or accumulator in an imperative loop, for instance), did it actually mutate anything?" The practical functional programmer would answer with a resounding "no". In fact, RamdaJS itself is implemented mostly imperatively internally for performance/compatibility reasons, but exposes a functional API for the consumer. Similarly, Clojure is implemented the same way for many of its core functions, and exposes an easy way for users to perform mutations for similar purposes within the functional, immutable-by-default language using transients: https://clojure.org/reference/transients

If you use imperative loops by wrapping them in this way, however, note that you're essentially implementing the same function signature of a function that calls map/filter/reduce on a collection, but with imperative primitives, and that's definitely a valid approach. If you build your programs by writing and composing these kinds of functions, you are in fact doing functional programming, and can reap all the composability, maintainability, and testability benefits that come with it.

I don't think there's any room to debate that most developers don't use imperative loops in this way, however. And my point was that the way they're usually used was not trivially composable. Of course, you could always refactor them into small functions that are trivially composable, but that they need to be to become composable is why I prefer using trivially composable primitives like map/reduce/filter to implement my programs as a default, and optimize specific functions with imperative implementations on an as-needed basis after profiling and identifying all the critical paths (premature optimization, and whatnot).

RE: `var sumOfSquares = pipe(map(square), reduce(add, 0));` not reading fluently.

This is where we'll have to agree to disagree. To me that reads quite literally as "given a collection, return the square of each item, and add the result of each to the next, starting from 0, to return the final value". The functional approach could definitely look more intimidating to readers without any general knowledge of functional primitives and what they do, but that's an issue of familiarity, rather than one of inherent readability.

Yes, people can get crazy with nesting multiple inline composed functions inside of other inline composed functions on one insanely long line, and that can quickly get out of hand in terms of maintainability and readability, just as people can get crazy with nesting loops. But that's just a case of bad functional code that needs to be refactored using a composition of smaller, well-named functions broken down into multiple lines. Nobody is claiming functional programming is a panacea for bad code.


It is not necessarily easy to recognize when a loop is a map or filter -- I think that's the issue. It's why someone like McSweeney would bring it up.

The Python approach -- where maps and loops share a lot of syntax -- is maybe the middle way. On the one hand, it's not an approach that gives rise to `.map()`, `.collect()`, `.flat_map()` and so forth; on the other, it's marked out as something returning a result.


The preference for maps and folds looks like a fad to me. I can use them but I don't think it makes the code any easier to understand, just different.


I dunno, ruby has some nice tendencies here, like `out = [1,2,3].map(&:to_s)` which is small and descriptive[1].

Compare that to:

    out = []
    [1,2,3].each do |x|
      out.append(x.to_s)
    end
IMO that's not fad material - that's progress. Maps and folds can totally be abused to produce inscrutable nonsense, but for small, common operations they're often much more obviously-correct.

[1]: `&:method_name` is extremely-common shorthand for "call this method"


I had no idea what you were trying to do in the first paragraph whereas without knowing much ruby I can easily read the intent of the second.


That has more to do with familiarity than anything else.

A tale of two cities is an easier book for an English speaker than Les Aventures de Tintin.

Map applies a function to each item in a collection.

As pseudo-code:

Collection.map(function)

And in the parents example we have:

[1,2,3].map(&:to_s)

The only Ruby specific part is &:.


It does though. Maps and folds - and functional programming in general - focuses on the /what/. For-loops on the other hand tell the compiler / cpu the /how/.

Summing is a nice example. A naive for-loop will just iterate through the list, keep a variable around, add the next item in the list to it. In functional programming (or with a reduce), you tell it to sum in a more concise way - but more importantly, you don't tell the compiler how exactly it should do it. It's trivial with functional programming to make the task (for example) multithreaded or to use advanced underlying cpu tricks, without you as a developer needing to know how exactly it does what you ask it to.


Consider product as a counter-example. With an imperative loop, it's easy to add an early-out condition if zero is encountered. But this is harder to do in a (strict) functional language.


This is exactly why lazy evaluation is often described as control-flow. Lazy evaluation permits efficient composition, without doing extra work (although the constant factors become much larger).


Yes, that's exactly right. And Go takes a relatively strict stance on making the _how_ obvious to the programmer. It goes out of its way to avoid hiding O(n^k) loops behind language sugar like map or fold, for example.


> O(n^k) loops

I'm unclear where algorithmic complexity is coming into this. Can you clarify what you're trying to imply?


map doesn't do any magic behind the scenes, it goes through a sequence exactly once.

Can you given an example where map might increase algorithmic complexity like that where the imperative version would not?


Map hides a loop behind a statement. That's all I meant.


You can hide a loop behind a function call in Go, Python, really any imperative language.

What makes map different is that it separates the looping mechanics (incrementing, initializing and appending to the collection) from the actual computation we want to perform on each element. It's just separation of concerns.


Yes. In Go, function and method calls are the primarily, perhaps only, mechanism of abstracting computational complexity. That is, when you see a function or method call, you know that "anything goes" back there, and you need to dig and find out what the computer is gonna be doing. Pretty much everything else is implemented "in plain sight"; in the case of fold/map, that means with a for loop, where you see precisely how many iterations you're going to step through.

You're right: map separates looping mechanics from computation. In Go, that's a bit too much obscurity.


A 70 year fad.


Maps and folds are implicit loops. For some explicit is simpler.


Maps are explicit transformations of data. For some, making the business logic explicit is simpler.


Loops are just implicit goto...

The argument for maps and folds is the same as the argument for structured programming in general: using common/reusable idioms brings clarity and familiarity.


Terseness doesn't necessarily bring clarity.


It's the recognizability, not the terseness, that brings clarity.

Although Python's approach is not terse -- `fstyle = [f(x) for x in arr]` -- it is eminently recognizable.

Your argument is not really about anything I specifically said; and without something to counterbalance, it argues against structured programming, too.


How does it argue against structured programming?

My argument is that "recognizability" is in the eye of the beholder. One programmer's "map is a powerful abstraction over transforms, for example loops" is another's "this is some cutesy code/math creole by a CS graduate who desperately wants to find nails to apply his functional programming and applied math hammer on".

That's a fairly harsh way of saying that at some point the abstraction isn't clarifying, whether it's recognizable or not.

Disclaimer: I'm a big fan of functional idioms (they're one of my favorite parts of Rust, for example). I'm not so much a big fan of absolutism or over-generalization.


No, maps are conversions between types containing other types. Maps are much more powerful than just doing something over an array in languages that support a functional style.


The original comment was comparing maps and folds to loops, not the general application of maps.


I don't know go, can't you write a map in it?


Not a type safe one that works on your own types.


You can't define a polymorphic function map, but you definitely could definitely define a map method for your own monomorphic container type.


Java reigns supreme because there is nothing which come close to its characteristics in terms of capabilities, libraries supports, tooling, performances, easiness to learn, simplicity and maturity.

If you want faster or lower level, you gotta move to C++, which is uber-hardcore in terms of non-simplicity and impossible-to-learn.

If you want easier, you gotta move to python/ruby/node.js, which are a joke in terms of performance and concurrency, with the last 2 being fairly young and immature (< 10 years).

Either way, the tooling sucks compared to Java, if not entirely non existent.

Entreprisey development is on Java because that's what best for them. Web development is on something else because they pick what's cool and trendy.


Ruby came out in 1995, 22 years ago. It is neither young nor immature.


Of course I mean ruby on rails when I say ruby.

Initial release 2005. i.e. Young.


Are you using Struts or something?

How could a 12-year-old framework not be old enough for you?


Ruby on Rails is a web framework, not a language. Also web dev is about shipping a product fast, that's why you don't see Java there.


You do see a ton of Java web apps in in-house and consultant-built line of business applications. Just not so much from product companies.


Once you know whatever java framework well enough and your project is not something ruby on rail spits out immediately, shipping fast is not a problem. In 4 months timeframe, you can definitely produce more or as much as with node.js or something like that.

The issue is that you wont do good frontend in it (obviously), java programmers are more expensive, learning it well enough so that you can actually be that fast takes a lot of time and hosting is way more expensive. Learning language itself is easy, but absorbing necessary frameworks takes time. Moreover, people who are good in frontend prefer languages similar to javascript, because they already know it very well so those are easier to learn for them.

I think this is why it does good in enterprise - they have money to throw at hardware, most projects are under huge time pressure constantly and requirements change constantly. Frontend is super important for product, but not so much for enterprise.


How is Java easy to learn, you need a huge IDE, I don't know how many SDKs or dependables and two pass compilation and 1000 layers of abstraction, ...


Try these languages in order of ascending difficulty: C, assembly, Delphi, Ada, C++

After that, you'll understand that Java is on the spectrum of "easy" programming languages.

The IDEs are very helpful by the way. You only need one SDK, which is a single download.


Ide makes learning easier and faster instead of harder. You dont have to care about compiler passes, ide compiles seamlessly.

But yeah, learning java ecosystem well enough takes a lot of time for someone who is just starting and you have to be comfortable with abstract thinking.


That is due to maturity / age, and at one point Java was the new kid on the block.


"Good" and "bad" aren't really useful descriptors without additional context. And what do you mean by "mid-quality" developers? That seems gratuitously insulting.


I think simplicity is often the most difficult to achieve and requires deep technical expertise to deliver. It shows the creators have thought about the end user and usage scenarios. It would be a mistake to confuse complexity with quality or vice versa.


IMO the Go goal is to be an enhancement of C. It is not as expressive as some existing languages (i.e., Go programs may be longer), but it is very good for translating clearly thought through logic into efficient machine code.

It supports some of the features that original C lacks (networking, parallelism, channels, etc.), which to me is a very good thing. With minimal forethought this allows writing programs that can be massively scaled later without impeding initial checkouts at small data sets.

Eventually the success or failure may be determined by the libraries developed by the user community. For example, fortran survived so long not because it was a good language, but because it had freely available, easy to use world class libraries for numerical computation. Many grad students kept using Fortran given the choice of an existing, working, ugly-ish code that they could use for their PhD projects vs redeveloping and retesting the same functionality from scratch.


In my experience writing go is very fast and reading go is also very fast. The language was designed to be very comfortable, and they did a great job with that. You sit down to write something and you don't have to think too much about the best way to tackle the problem, the lines of code just flow from your fingertips. There's mostly one way to do everything, which makes doing things easy.

Code review is much the same.


The legibility and simplicity are my favorite things about Go. I know that I can fearlessly dive into other people's source to figure out what's going on without running into 15 levels of indirection hell and a bunch of language features/idioms that I'm not familiar with for one reason or another.


I feel the same. Go is a different type of terse. I think terseness goes beyond the number of lines. When I skim Go code, I can grasp the meaning of it very quickly.


I've seen talks where Rob Pike describes Go as being "light on the page" vs. "noisy", meaning (I think) that it doesn't have lots of sigils and annotation bits around the code.


And those are the secret ingredients of a great language for team programming.

And thats why Go will dominate the market that once was meant for Java.


I really hope not, there is already a lot of awful code around written in Java. I can't imagine codebases on the MLOC range written in a language even worse than java 1.4 (it didn't have generics, but at least it had exceptions)


"bussiness" languages will never change. It will be Cobol, Java, C#, Go, and then something like that in the future.

The truth is, theres not enough smart people to do things in the hundreds or thousands in a more sophisticated language.

And also speaking of smartness, sometimes, using simple tools, can help you focus on algorithms. Linus and crew coded the whole Linux in C, a language with very few resources, and considered pretty ugly by today's standard.

So i can see the beauty of that, even when you are able to use any sort of more sophisticated language, sometimes chosing something that can be shared with more people can pay off, instead of a more "elitist" language, with a higher barrier of entry. And also lets not forget, that theres always some economics at play. Where companies not focused in IT will choose tech that can scale by the number of employees, do its job and be cheap as possible.

I think there will be no antidote for that. It will always be some reincarnation of Java.


There are MLOC of awful code in every language including your favorite.


There are already MLOC projects in Go like Kubernetes, Docker etc.


Libraries may be a stumbling block for Go, though, because C interop is somewhat slow. Photoshop, Python, Postgres, &c are not all likely to support plugin/extension interfaces based on Go calling convention anytime soon.


I'm concurrently learning Go and Node, which might not be a fair comparison but I'm going to make the comparison anyway.

Node feels like a flesh wound with delicately layered bandaids. The ecosystem is a mess, you have to jerry rig basic packages to work together, the syntax and semantics of closures and context is ridiculous, and despite that callback mania is like this cool-aid that's supposed to feel great once you drink it (but hasn't yet for me).

Go just...works.


Hehe, I have to underline this aspect as npm killed half an hour of my work yesterday, when I redownload some package in a sibling directory (for diff purposes).

Never had this experience with go. The comparison is a little emotional for me, but when I realized npm just killed my code, I was emotional...

Nevertheless, Javascript/Ecmascript is the result of years of development in a living environment (the web) while go was designed from scratch, by some of the most capable programming language designers on this planet, to enhance their previous work. Who wonders about the result?


My impression is that Go is a language that was cobbled together to simplify the coding of some specific applications, such as simple servers. It lacks any kind of purity, is not the best choice for any specific task, but is just good enough for some (many?) tasks. And poor type safety!

Frankly, I can't help being disappointed by how bland this language is, and I have zero interest in using it. Maybe because I like coding, and the IMHO using Go or Java would totally kill the fun of it.


To each their own. I enjoy writing Go almost as much as writing Python. But more importantly I find reading Go easier than any other language - mostly due to its explicitness and consistency between authors. That has made it much easier to dig into code bases that solve some very complex and interesting (to me, anyway) problems.

Also, I assume the 'no type safety' statement is just hyperbole?


They probably mean you can use interface{} and create a typing black hole if you really wanted to. Otherwise, I don't know.


Or maybe they mean that you HAVE to use interface{} for any reasonable kind of generics, such as developing generic data structures, or generic handlers for RPC interfaces allowing arbitrary nesting?

Even the stdlib uses interface{} everywhere now: https://tip.golang.org/pkg/sort/#Slice


Is a good point. Smells of void pointers and old school Java collections.


I've always believed that blandness is the reason why the language was created.

Google has a ton of developers working on a giant codebase. If Google were written in something interesting and complex (eg scala or ocaml) then some parts of the codebase would be remarkably complex while others would be simply a ton of library imports and then something procedural. Whether you are in the former or the later would be developer dependent.

Now, say you're a Google exec, you know you're losing a ton of developer hours as people ramp up to different parts of the codebase and that some parts are so complicated that only a few (expensive) engineers could ever work on them. The more you can remove differentiation between engineers and commoditize programming the less expensive specialists you'll have to deal with and (hopefully) things will get cheaper. There's a size at which the investment in creating a new, bland, language will pay off for you - hence golang.


It's more than "bland." There's a whole lot of "just works" in the whole ecosystem.

Now, say you're a Google exec, you know you're losing a ton of developer hours as people ramp up

Why wouldn't ramp-up time be a big company's most significant cost?


But if you like typing `if err != nil` it's actually the most fun language.


Heh, it does feel repetitive. But after ~10 years with Java, I'm happy to avoid the cognitive load from deciding how to most politely generate/propagate an exception. Obviously, there's no perfect solution, and preference is subjective.


In reality Go makes it worse, if you truly keep track of all possible cases. After calling a method, in Go you have to

1) "if err != nil" after every statement

2) give some serious thought to whether the previous statement could panic or not

Good luck if it's a library call that may get updated or call other libraries !

3) Think about the non-error error cases that can't be abstracted out. Go is like C, in the sense that there is an ERETRY "error" (unsurprisingly, you should simply try again, you should NOT fail)

And there are cases where there can be an error and yet error is nil. Easy example of this would be sscanf.

And we now see practical Go code published online : how these problems are dealt with, real world edition:

1) either mindlessly putting "if err != nil { return err }", which is a very bad information-erasing exception system, or just outright ignoring errors. Don't you know you can also use "_" as the error variable ? Maybe they should make that implicit like in perl. Of course perl is likely to tell you this happened ... unlike C and Go.

(really brings back the C days doesn't it ?)

2) most people either don't know or just deny this. Thankfully panics at least do list where they occur. They also kill your program and print stacktraces. Pages and pages and pages of stacktraces.

3) very few people even know about these problems ... so they're ignored, and the standard Go tools themselves don't behave according to unix specifications.


Panic is pretty much never used (so you don't really have to think if the previous statement can panic. If it does it means something is SO wrong that your application can't continue anyways because it's broken)

You should really use a library like github.com/pkg/errors so you get to wrap the error you return with additional information. Errors are just a worse Either monad after allm they're much more pleasant to use than exceptions.


> Errors are just a worse Either monad after allm they're much more pleasant to use than exceptions.

How are errors in Go at all monadic? They just have a convention where you return a tuple and manually check if something isn't nil. Either type will inhabit one variant or another, not both with one having a value of nil.

The 'monadic' part of Either (or Result in something like Rust, where try! is sort of like >>= if you squint) is the ability to chain Either types together and have the boilerplate abstracted, that feature is completely absent from Go. Errors in Go are neither the Either type nor monad, IMO.


As I said, in practice they're a worse either monad. With which I meant -> they were inspired by them, but lack the monad part and having the value with the error in one object interchangeably. It's the same treating errors as values though.


It's really just a worse Either type, if anything, there's nothing monad about it. Although it's sort of hard to be close to an Either without being an algebraic data type. But I see what you're trying to say.


> Panic is pretty much never used (so you don't really have to think if the previous statement can panic. If it does it means something is SO wrong that your application can't continue anyways because it's broken)

That's it. I think OP just assumed panics in Go are what exceptions are in other languages.


Because the stdlib is using them more and more? As someone mentioned, even closing an already closed channel can panic. Calling the random number generator with a negative limit panics.

And there’s nothing like checked Panics so you’d know if one will happen or not.


As I said, if your code is plainly wrong then I see no problem in it going haywire. The channel rules are widely known -> you know, it takes more than a few days to learn a language, there are a few rules to learn too.

Calling a number generator with a negative limit is also a programmer fault, so no reason to provide an error here.


Yes, there is no problem as long as you agree with X about what is a "real" error and what isn't.

X includes

the language authors (who are using this more and more in the stdlib as pointed out elsewhere)

the authors of any library you use ... but

transitively, so this includes the authors of any library you use indirectly as well

Hmmmm ... what was the problem with (unchecked, or python's) exceptions again ?


I see nothing wrong with that - those _are_ fatal conditions that indicate that something is dangerously wrong in the program.

And those panics do give you a helpful stack trace, complete with source code line numbers, so it's easy to find the culprit (as opposed to "bubbling up" exceptions).


These uses of panic look a lot like the canonical use of unchecked exceptions in Java: the programmer has made an error, which they could have avoided. It's a bug. There's no point returning an error and letting the program try to recover, just blow up with as much information as you can, so the bug can be fixed.

The canonical use of checked exceptions in Java is for unpredictable events - almost always related to interaction with the outside world, like IO, networking, parsing, etc. These are things the programmer can't prevent, and must defend against, so the type system allows, and in fact forces, the programmer to explicitly address them.

This is all explained beautifully, and at length, in this monograph:

http://joeduffyblog.com/2016/02/07/the-error-model/


> There's no point returning an error and letting the program try to recover, just blow up with as much information as you can, so the bug can be fixed.

Well, imagine a game letting the user roll a dice. "Chose a number of sides for your dice".

In such cases, handling such a panic might be useful. And knowing that it exists might be useful, too.

If the language does not allow specifying a range of a type (for example, requiring all numbers passed into the RNG to be positive), then it should be specified in the API in other ways programmatically, so it can be statically analyzed.


You should ALWAYS check the input you get from users. So this really wasn't a good counter argument.


As I said above, panics should ideally never be able to occur, but be part of the type system.

In languages with dependent types, for example, it’s common to represent a Stack in a way that number and type of elements are stored in the type (so you can’t even pull from an empty stack – that’d be a compile time error).

In the same way, the random number generator should either return an error, or use a number type that can only encode positive numbers as input.

Especially if combined with the interface{} everywhere across the new stdlib functions this all smells very much like C's problems.


It's the same cognitive load, really. Instead of deciding how to best propagate exceptions, you're now deciding how to best propagate the error value.


Not really. In a language like Java, some of the questions I'd have to ask myself are:

  - Should I try to catch the exception, or just let it 
    bubble up and edit my interface to include it?
  - Should I create a new exception type or reuse an existing one?
  - Should I throw a checked or unchecked exception?
  - Am I exposing implementation details via my interface? 
    (eg I don't want to throw an SQLException from GenericDataSourceWidget.connect())
In golang, I know there's really just the one pattern: check if err != nil, prepend a descriptive message, and return it.


>check if err != nil, prepend a descriptive message, and return it.

That'd be the RuntimeException equivalent, sure. But what do you do for the equivalent of checked exceptions? Errors are frequently recoverable, "err != nil" alone does nothing to help you there, and string manipulation is a horrific alternative to types.


You can have typed errors too. This is fairly common in Go. As long as it implements the Error interface.


At which point you're back to the original complaint of:

  - Should I try to catch the exception, or just let it 
    bubble up and edit my interface to include it?
  - Should I create a new exception type or reuse an existing one?
  - Am I exposing implementation details via my interface? 
    (eg I don't want to throw an SQLException from GenericDataSourceWidget.connect())
(except for "- Should I throw a checked or unchecked exception?" since that's fairly Java-specific)

To me, those questions seem unavoidable, and sweeping them under the rug is a false simplicity. You're exposing things - what do you expose? How should the caller deal with it? Is it the same as [other thing]? I'd much rather have the type system involved, since error handling is pretty critical to correctness/stability. If go's giving up the safety, what does it get in return?


I feel like the type system is involved? If there's a problem it's that Go doesn't make throwing typed errors a common convention (and we lack the tooling to make handling them a habit I.e. inspect this call and find me all the error types which can come back.


> I'm happy to avoid the cognitive load from deciding how to most politely generate/propagate an exception

This is like saying "I'm happy to avoid the cognitive load of having to specify how my code should behave in case of an error".

Sure, your code is simpler as a result. It's also more buggy.


It makes cyclomatic complexity explicit that is otherwise hidden by exceptions.


How's that different from typing `for`, `switch`, or any other way of using a language?


It's used very heavily for everything container related. It seems to be an excellent fit there, at the very least. It's also becoming an increasingly popular choice for startups when they need performance, which used to be something Java or C++ were typically used for.

Personally I've had a lot of fun using it, but prior to starting with it I'd mostly done Java and Node, so that may have something to do with it.


I'm not convinced that using startups as a metric for anything programming related is a good idea. At least not startups here in the Bay Area, which seem to me to be very fad driven.


Today's startups are tomorrow's huge stack of legacy software that Nobody Wants To Touch Because It's Our Core Business though; I'd say Go is a pretty good choice for those due to its simplicity and shunning of 'clever' code. Companies like Paypal, Ebay, and probably a few others have (had?) a huge load of old Java code and only recently spent a lot of time cleaning that up (iirc Paypal went with Node, at least for its forward-facing things)

I don't know how maintainable 10-year old Ruby code is though, on the other hand.


Today's startups are, mostly, tomorrow's failed businesses. The majority of the most successful startups of the last 15 years have generally used tried-and-true battle tested technologies in their successes: Java, C, C++ and PHP.

This isn't to say Go doesn't belong in that list, but simply to reinforce my point that what startups are using today shouldn't be an indicator of high quality technology that can (or should) gain more traction and use in the future.


And Ruby. Ruby is basically the new Java. As in it's no longer cool but is considered battletested and is now at the core of 10+ year old companies with code bases just as old that noone enjoys working on anymore.


That may be, in which case Python belongs in the same bucket. I'm not convinced, actually. Most of the "ruby shops" I know use it only for the most trivial of applications, being essentially rest-like proxies between clients and Java (or other language) services. But I don't know everything and anecdotes aren't data for sure.


That legacy software has come out of the web or backend stack of startups? Most of Facebook is written in PHP but Cassandra is written in Java.


That is a good point, and it definitely is. But in this particular case I think it makes sense, although there's probably a "shiny" factor to it as well.


How can you write an efficient container without generics?


Use a language that has generics.

Snarky, but its such a tiresome argument. If you need something Go does not supply, use a language that fits your needs. There are a lot of programmers happy in Go, and thus happy without generics.

There are programmers who are happy using generics, thus write in Rust, Java, etc.

There is no language to bind them all.


By copy and pasting or code generation, as we've unfortunately had to do. Makes for messy things like DateRange paired with DateRangeInterval tree vs. a generic Range that works with an IntervalTree.


Container as in "Docker container"


That's just a jailed process. There's no reason to need a completely different language, especially one without any specific support for running untrusted code.


Well clearly that isn't a requirement, it just so happens that Docker, rkt, and most related technologies are all built with Go. etcd even uses grpc


gRPC isn't Go specific in any way. In fact I would imagine it's main implementation would be in C++, secondly Java and then maybe Go.


I keep reading this and I keep wondering what's stopping someone familiar with language design from writing generics code


They seem to take a lazy approach to feature development. Generics are complicated and bad, but having makeIntMap or makeStringSlice is...not great for developer productivity.

So let's special case `make()`, slices, channels, etc. so that some productivity is possible.

Then as they add library features they violate their own tenants as they find utility in these verboten constructs. Exceptions are bad...But we have panics which are in no way the same thing renamed. Never expose them outside a package...But closing an already closed channel panics. Random number generator functions panic on mundane and expected things, just like Java checked exceptions.

Example:

https://golang.org/pkg/math/rand/

``` func (Rand) Int31n

func (r Rand) Int31n(n int32) int32 Int31n returns, as an int32, a non-negative pseudo-random number in [0,n). It panics if n <= 0. ```

Standard behavior would be returning an error, not panicking,

See this:

https://blog.golang.org/defer-panic-and-recover

``` The convention in the Go libraries is that even when a package uses panic internally, its external API still presents explicit error return values. ```

It's just an inconsistent and, quite frankly, disappointing language outside of goroutines and its interfaces. Those two make it possible to be productive, but with generics for instance a whole slew of new possibilities will emerge.

The simplicity is nice, but it's too simple and too inconsistent. All the verbosity of Java combined with the impenetrable inconsistency and abbreviations of C.


I wonder this too. For how important generics are claimed to be, it does seem strange that nobody has stepped up and helped out the core team in this capacity. They have been quite open about wanting generics, but do not have the resources to dedicate to implementing them in an acceptable fashion. But being an open source project, anyone can step up to fill that void.


How can a google backed project not have the resources?


I don't know, but Google does frequently complain about not being able to find talent. Some of this is through fault of their own, but it is easy to imagine that they have not found suitable developers to fill the spot, for whatever reason it may be. They have lots of other business goals for what developers they do have. Putting their people on generics at the cost of some other business function may not be a good choice, even if it is theoretically possible.


It would be wasted work, because no one in the community would take it.

So better spend that time contributing to other parts of the Go ecosystem, or another programming language project.


I've been thinking about a two way compiler with a primary focus on producing readable code. If such a compiler targeted Go or Java, you could white your "Go+" code (for lack of a better name) in a higher level language with more features, and have it compiled to readable Go code. I don't know to what extent this is possible, but if it was good enough you could be a Go developer while rarely writing actual Go code.


It is very much possible, there are already DSLs that generate Go code. I'm even doing that myself.


Can you link some examples?


You can have your generics and many other nice things combined with the gccgo goroutines, channels and garbage collector by switching to Nim: https://github.com/stefantalpalaru/golib-nim


> And no type safety!

90% type safety (probably even more) is more than no type safety. It's not a holy grail that all programming must strive for.


It's a balance, but I am fairly disappointing that such an up-and-coming language has such a limited type system. In the days where even traditionally fully untyped languages are moving toward inferred, optional and static typing [1],[2],[3] I'm disappointed to see `interface {}` sprinkled throughout Go API's.

[1] JS Typescript and flow: https://www.typescriptlang.org/, https://flowtype.org/

[2] Python with mypy: http://mypy-lang.org/

[3] PHP with Hack: http://hacklang.org/


> In the days where even traditionally fully untyped languages are moving toward inferred, optional and static typing

This only shows that the sweet spot is probably not in the extremes, but somewhere in between the dynamic type system - paranoid type system spectrum.


Go's blandness is a feature to me. It's not a joy to write but pleasant to read and understand which, sadly, won't matter unless Golang gains more popularity.


100% agree re: readability (as I've mentioned elsewhere).

I've actually been very surprised at the near-ubiquity of Go in the modern infrastructure/tools space though. Seems like each new OSS product I evaluate is written in Go. See companies like Cloudflare, Hashicorp, InfluxData, CoreOS, and, obviously, big projects like Kubernetes.


I think that's mostly because Go trivially generates static binaries, and cross-compiling is also trivial (as long as you don't use CGo).

I can't actually think of a single other language that matches that. Rust might get there one day but cross-compiling still requires a C cross-compiler (ugh) and C dependencies (e.g. OpenSSL) are often dynamically linked.


Cross compiling shouldn't require a C compiler unless you have a dependency on C code.

Most wrappers should at least provide an option to statically link the C; I know the OpenSSL ones do.


Not a C compiler, but you need a C linker, which is just as much hassle. Apparently there is work going on to use LLVM's lld linker, which I guess might support cross-compiling in a sane way but I haven't checked.

And yeah most wrappers provide a static linking option but there's not much consistency which is rather annoying.


Go is meant for distributed systems. All these companies, and generally speaking a lot of infrastructure thing is in that domain. They use the right tool for the job.


Can you elaborate on why Go the language is "meant for" distributed systems?


It has been explained on multiple occasions by the language designers what they meant it for, e.g. https://talks.golang.org/2012/splash.article


For me, Go is the most fun language I've ever used after 15+ years of programming. I like how simple and consistent, yet powerful it is.


I don't disagree about the type safety and general qualities of the language, but saying "Maybe because I like coding" is really unnecessary language egotism. There are many, many people who love coding and love doing it in Go.


Personally I like Go; it's a very fun language for me. It's true that it sometimes feels like a language designed for the precise purpose of writing daemons, but that's exactly why I like it.

The thing about Go is that its opinions on concurrency are ones I share, to the point where I was practically waiting for something like Go to be invented. Other than say, Erlang, I'm not aware of many alternatives which provide a) ultra-cheap coroutines (10,000 coroutines? fine!), b) an I/O system which is seamlessly integrated with that concurrency system (and in a totalitarian manner at that; if you're using Go, you're using its event-based I/O scheduler, no exceptions), and c) a rock-solid runtime.

[IO SYSTEM.] The imposition of Go's I/O system is important, because it means all Go code is written using the same I/O system, which makes code reuse much more feasible. The chances of you being able to integrate a random OSS library that you discover in say, C++ into your C++ project is much lower:

I call design decisions that pervade every line of code in a project "cross-cutting considerations" (CCCs). These are design decisions where changing your mind means rewriting every line of code, or at least reviewing every line to see if it needs rewriting. Your ability to consume a library depends on where your project and the library sit in CCC-space, an n-dimensional space. If your project is written using an asynchronous I/O reactor, and the library uses a traditional synchronous, sockets-based programming model, you're screwed. You can't use that code, unless you maintain a fork (and in that case you'd have to transform the library into the continuation-passing style, etc.). If the I/O is pluggable, you have to go through the effort of plumbing it into the reactor library you've chosen to use, just to be able to consume that library.

Not only does "using Go" imply the I/O system that goes with it, Go's tightness in language design means you don't see the feature rejection that you see in a language like C++. C++ isn't a language, it's a family of languages; everyone chooses their own subset of C++ to code in. Some people think exceptions are bad and avoid them, and some people think templates are bad and avoid them, etc.

What this means is that the statement "this library is written in Go" is a hell of a lot more meaningful than the statement "this library is written in C++". It's not just C++ either; Python for example now offers a wide variety of choices for I/O, which inflates the CCC-space across which the language's ecosystem of libraries are distributed. One library could use asyncio, one something Twisted-like, one synchronous calls, one threads, etc.

[COROUTINES.] It's the right way to do concurrency. Not the continuation passing style; it's truly preposterous that programmers have been made to write in a format originally intended to be implemented as a compiler transformation. Only recently are we seeing languages augmented with async/await keywords to allow this transformation to be performed behind the scenes (JavaScript, Python 3, C#). Erlang has been around a long time making the CPS look ridiculous, and later there was Stackless Python, an ignored gift horse to the Python community. Stackless Python failed to be a real alternative to Erlang, Go, etc. because it never managed to get a thriving ecosystem or IIRC, a standard I/O system around it.

I also perceive that Go has almost completely accidentially obtained some additional fondness for the fact that it produces statically linked, portable binaries. If you're shipping only Go code, you may often be able to get away without using containers when they'd otherwise be essential. You see Go binaries for Linux being distributed officially by OSS projects when normally for Linux that's very rare; it's left to package managers, and you have distro differences making compatibility potentially tricky.

The fact that Go shipped with a standard, configuration-free build system also makes creating new libraries, or bringing in existing ones almost completely frictionless. Even if you think Go is boring as a language, what really makes it stand out is its execution. Just look at how they're improving the GC with every release.

(This turned into an essay... I guess my ultimate point is that getting a coroutine-based highly-scalable I/O programming environment to work as an ecosystem requires you to standardize on one runtime completely and utterly, and be able to trust that runtime with production workloads. The only such systems I can think of which are stack based and which formed successful ecosystems are Go and Erlang; though now we're seeing a lot more CPS-based systems using async/await annotation, which are probably more than good enough for the same applications. Although I would point out that neither Python 3 nor JavaScript are trying to occupy the multi-thread m:n scheduling space in the same way that Go and (I think?) Erlang are. They're constrained to essentially single-thread operation.)


> Other than say, Erlang, I'm not aware of many alternatives which provide a) ultra-cheap coroutines (10,000 coroutines? fine!), b) an I/O system which is seamlessly integrated with that concurrency system (and in a totalitarian manner at that; if you're using Go, you're using its event-based I/O scheduler, no exceptions), and c) a rock-solid runtime.

GHC Haskell.


Also Akka for Java/Scala.


Re: green threads

The C++ Actor Framework is awesome

https://actor-framework.org


It lacks any kind of purity

What language is pure anything? Even Smalltalk wasn't pure Objects. Programming languages are pretty complex. If you look deep enough, you'll find the leak in the abstractions.


Not using Java the #1 server language? What do you code your server in C++?


Some(A lot of?) people use programing language just for day job. For them Java or Go would just do fine.


> It lacks any kind of purity

Example of lack of purity?


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

Search: