Go: Ten years and climbing
commandcenter.blogspot.com
commandcenter.blogspot.com
That said, I've always hated the trends that have brought Golang into popularity. The engineers I've felt who could benefit from Golang the most could also benefit by getting a better handle on their fundamentals and taking a moment to design their codebase more. As a simple language to wire pieces together, Golang is fine, but it really doesn't give you the tools (imo) to be productive for anything more complex than simple apps. It's a great alternative to JS (again imo), but not something I'd like to write.
We shouldn't need to treat the developer like a toddler to get them to write safe code. I'm a much bigger proponent of languages such as Rust or Haskell which give the developer the _tools_ to ensure their own data integrity, but I guess that says something about me as a developer and why I don't like Golang.
Are Docker and InfluxDB simple apps? What do you consider simple and what do you consider complex?
Docker and InfluxDB are investor funded organizations that contribute to open source. I'd argue that their success has more to do with the monetary input than anything to do with the language itself.
You're absolutely correct on basics, and those can't really be worked on unless devs are stripped of everything but basic constructs like the function. Rust and Haskell are too much for the average dev and maybe even good devs
How do you address its popularity in the field of cloud computing then (which I presume you would agree is pretty complex)? This was mentioned in ample detail by Rob in the article. Is Kubernetes not a "productive" system by your definition?
Go was simply the first language to successfully target the niche of imperative, natively compiled, GCed languages. It wasn't the first language of this kind, but the first to have a reasonable amount of adoption/backing. Whatever other flaws it has or had were trumped by the lack of serious competition in this area.
With Go, you're getting a lot of high-level language features like anonymous functions, while also gaining the control that you're not able to get in higher level languages like Python or Ruby or Java.
I think this works out great for cloud computing, where performance is a major requirement, but the technology is expanding rapidly enough that a step up from C or C++ is very necessary.
A lot of the complaints I hear are related to abstractions, too, and I understand those to an extent. I also think that if you're complaining about the lack of generics, maybe you're not thinking about interfaces correctly. A perfect example is the beautiful simplicity that is the [`io.Reader`](https://medium.com/@matryer/golang-advent-calendar-day-seven...).
So, whenever someone says something like the OP:
> As a simple language to wire pieces together, Golang is fine, but it really doesn't give you the tools (imo) to be productive for anything more complex than simple apps.
I take that as meaning, "I've never seriously used Go beyond writing a hello world app. It doesn't have the features I rely on to be productive, therefore I don't think it's a capable language for larger projects."
I will say though, dependency management in Go is hell. I wish Go had something like Cargo.
This is the number one thing that has kept me from going full on Go. The killer feature of Node was NPM, not Javascript. Unless Golang comes up with something comparable it will forever remain niche.
There's a lot of "gotya"s with using dep though.
One that gets me a lot is the fact that I like to commit my vendor folder, just for faster CI.
So if I committed my vendor folder with a copy of "k8s.io/client-go", and then in a different project I imported a package from my vendored project, it would never compile until I removed my local copy of that "vendor" folder, since it's looking for that specific dependency ("my-project/vendor/k8s.io/client-go").
Not sure if I explained that super well.
If I have project A, which imports dependency A. I (for faster tests is the only real answer), decided to commit the vendor folder.
Now, in project B, if I import a package of project A, which uses dependency A, it will look for that specific version of dependency A. Specifically errors like this:
pkg/projectb/example.go:18:30: cannot use *w (type "github.com/dependency/pkg".Example) as type "github.com/project/a/vendor/github.com/dependency/pkg".Example
It's not a big deal because if I just remove "github.com/project/a/vendor" from my $GOPATH then the problem is resolved.because of this, I guess my real complaint here is that "vendor" doesn't seem to be the right word. I'm really just looking for something to complain about.
So your problem is you have ("binary") packages A and B, and a helper package at A/H that you want to import into B. But A is vendored at A/vendor, so A/H always looks for dependency D at A/vendor, which is wrong for B.
I would fix it by moving A's main into A/cmd, and vendor at A/cmd/vendor instead. A/cmd can still import all its' helper packages like before, but now B can also import them without getting snagged by A's vendoring because it vendors another level up.
Could that work?
My solution was just to not commit the vendor folder, and before the test starts, run "dep ensure".
But then again if you're only testing H against A's vendored dependencies specifically, you're missing testing it against B's. I'm not sure how you would fix that.
I didn't realize they were working on solving this, that's fantastic. Hopefully it can gain traction.
> dep still has nasty bugs, but in general these are comparable or fewer to other tools out there.
(From the Github readme)
I started a project about two months ago and wanted to use Dep, however there were a few show stopping issues for that. Most prominently Go has issues with upppercase/lowercase repositories, meaning if one of your dependencies imports github.com/Sirupsen/logrus, and you or another dependency imports github.com/sirupsen/logrus your code won't compile, no matter if you are on a case sensitive system or a case-insensitive system. [2] The aforementioned logger made a switch in the naming which caused problems while most were migrating the import. The docker distribution in its latest stable version still uses uppercase, while others use the lowercase.
Dep follows the Go specifications and at the moment just throws an error, before, they didn't handle it at all.
So I had to resort to a different dependency management for now, which did some linking to fix the situation.
[1]https://github.com/tools/godep [2]https://github.com/golang/dep/issues/1010
I've not tried it for a while now but last I saw it was even more opinionated about GOPATH than the existing tooling, and it wasn't at all easy to figure out what it wanted me to do. Maybe it's improved since though.
You can see the idiot friendly language eclipse in popularity in other domains too even though "better" alternatives exist:
- elegant general purpose: python over ruby
- web: php over python/rails
- SQL databases: MySQL over Postgres
- NoSQL: MongoDB over CouchDB/Postgres
Go's just the first mass appeal language in the concurrency performance domain and it just opened the door to a lot of developers who before wouldn't dare play in the space.
So while you might like ruby/python because it's prettier or because PHP 4 was awful, the idea that one of them is a better web language is totally laughable. If you asked me to define a language better than PHP for web applications, I would have you a long list not even considering python and ruby.
I'd also suggest that an army of experienced devs is more effective than an army of non-experienced "toddlers". Programming languages and CS fundamentals aren't elite, impenetrable cliques; they can be learned.
And the choice of language is incidental for the most part as well.
Depends on what you mean by toddler.
Golang devs imo are not toddlers. The point seemed to be that golang devs could just learn to write C, which is valid. So could Rust developers. But if that was the goal, you'd think both groups would only be using C.
When I think of "toddler" developers, I think of interns being hired into a company to write code with no experience working under mid-level developers that also lack experience, and 5 years later you have what is called f-ing hell. I've worked at a company like that before, and know someone that worked in a company that was mostly VB developers. Same concept but without interns.
With enough fuel, fire, and gained wisdom, anything is achievable.
But, 10 kids playing with building blocks can't easily build an automobile, whereas one smart, dedicated engineer with a lot of metal, some tires, and better tools could pull it off. So, tools and resources matter, too.
This is a little smarmy, don't you think?
You seem to come ever-so-close to hinting something like "Go isn't fit for writing real applications." Without getting into what exactly a "real application" is, I'll just say I think this suggestion is wrong, unhelpful, elitist, and just generally irritating.
The criticism of Go being presented is that it's intentionally underpowered so as to make it possible for poor developers to verbosely muddle their way through to developing working real applications without actually becoming better.
Only the most cynical view of the language would see it that way. Just because they don't agree with your programming worldview doesn't mean they are idiots. The fact that people can say smarmy stuff like possible for poor developers to verbosely muddle their way through to developing working real applications without actually becoming better with a straight face just shows how closeminded and ideological people get about languages. Just because you know what a monad is or use map/reduce/filter plentifully doesn't mean you are a better dev than someone who has spent years honing their skills in an imperative language.
Nobody gets this ideological about natural languages. Nobody in the real world says "Hey, why are you speaking Spanish? It's so inefficient, you should be speaking Mandarin". Just as in natural language, programming languages can be learned and adapted by people of varying proficiencies, and when you "get" their particular way of modeling the world, they become an extension of you and a tool. We should just be happy when people become really good speakers of a language, not whether it is the right one.
Do people really believe that individuals such as Rob Pike, Ken Thompson, and Brian Kernighan are just trying to propagate Blub, the language, so that all devs are lowest common denominator morons? Have you seen how clever some of things they've built are? I dunno, maybe some of the original hackers have learned a lot about building complex systems over the last 50 years, and maybe they've got something useful to say.
For natural languages, the research seems to indicate that information is transmitted at the same rate when the languages are spoken (e.g. http://muse.jhu.edu/article/449938/pdf) with faster speaking rates compensating for higher verbosity. In terms of writing systems, though, there's definitely a ton of human potential being frittered away on learning Chinese characters and esoteric English spelling rules, but not much that can be done about it even if the Korean alphabet and German rule-adhering regularity are superior. Programming languages are all faster to learn and are iterated on much more quickly and so the possibility of realistically affecting change leads to ideological arguments.
It's also to separate itself from the Java crowd, which has a rather poor image to a lot of people that google wants to attract.
As it happens, outside of (perhaps) Google, C++ serverside development is so rare that Go's strengths aren't very compelling to C++ developers. That Go didn't evolve in the direction its founders expected does not mean that its founders are lying when they explain, clearly and repeatedly, what the original point of the language was.
Java didn't cut it for Google because see my previous post.
It was Pike himself that stated that as a goal for Go at one of the early Goconfs, because new Googlers aren't skilled enough to pick up C++, Java or Python.
If you wish I can track it down for you.
That's the quote people like to jump on. You could read it as humility or a nod to other languages, but it probably wasn't intended to be read as "we've designed a stupid language", and even if Pike agreed with that reading, he probably wouldn't agree that keeping programmers mediocre is a goal or a side-effect of a non-brilliant language. Don't mean to put words in his mouth, but the above quote obviously isn't meant to support anything like:
The criticism of Go being presented is that it's intentionally underpowered so as to make it possible for poor developers to verbosely muddle their way through to developing working real applications without actually becoming better.
Which is an extreme criticism, but it's a pretty common assumption in most of these discussions. I mean, look at the most upvoted posts in this thread.
> "The key point here is our programmers are Googlers, they’re not researchers. They’re typically, fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They’re not capable of understanding a brilliant language but we want to use them to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt."
It seems opposite of what you mentioned regarding C++/Java/Python.
I love the quip, but
> people literally said it about assembly language. If for no other reason than to preserve your own dignity, please don't imply that people program in a particular language because they're not good enough to program in other languages.
This is an inversion of the sentiment being expressed: the suggestion is to use languages that allow you to shift more cognitive overhead to the compiler and tooling. If anything, I program in Rust when I fear that the keeping track of all the little bits Go doesn't help me with will take up too much of my puny human brain.
As the sibling comment points out, you managed to misidentify the trope to boot.
You talk about giving the developer tools, but those tools can be augmentations on top of the basic building block that is the language. That way, anyone can build tools for their needs, without complicating the lives of others. No need to build all the tools into the language, that's very constraining.
This is a thing that's commonly repeated, but it's not that, well, simple. Having a simple syntax doesn't matter that much for tools once you have a reusable parser library.
More important for tools is having a simple semantics. Do all builtins behave the same way? Is nil handled consistently (e.g. does indexing a nil map do the same thing as indexing a nil slice)? Are the coercion rules simple? Is importing a package free of side effects? (The answer to all of these for Go, unfortunately, is no.)
The most important thing, however, for tooling is whether the language provides static guarantees. For instance, if the language controls access to shared mutable state, you can do a lot to detect races statically. As another example, if panics were part of the type system, then you could statically know whether functions panic and, if so, what types of panics can happen. Here, Go provides very few static guarantees: it's very difficult to soundly prove anything interesting about Go programs.
Unfortunately, you can't really have it both ways: you can have a more dynamic type system that doesn't put many constraints on on programs, or you can have interesting static tooling. Go chose the former in nearly every instance.
That said, if you're trying to argue that autocompletion is more difficult to implement for Rust compared to Go because Go is simpler by some metric, then I disagree there too. Any static language (well, one that doesn't intertwine parsing and semantics like C++ does) can support autocompletion with comparable levels of implementation effort.
Anyway, regardless, there's certainly more work to do! And it's being actively developed quite heavily. For example, it will be on stable Rust very soon.
As a big Rust proponent, I don't think it makes sense to invoke Rust here. The goal of Rust is to provide a more secure low-level foundation for software; any tools it provides to "ensure data integrity" are in service of that end, and pale in comparison to the sort of correctness that Haskell strives for on principle.
Given that Go is memory-safe (modulo a few concurrency foibles), any software that gets rewritten from C to Go is still a win in Rust's eyes. I know more than a few people in the Rust community who are big fans of both languages (e.g. burntsushi, author of Rust's regex library and ripgrep), and the Rust developers have a lot of respect for the Go authors. Go and Rust have different priorities, and that's A-OK.
The end goal is that the overall software stack should become safer, regardless of what layers one is actually busy with.
I write raft based distributed applications in go, it uses millions of raft clusters concurrently just for its nightly tests. That simple app is not that easy.
Introducing too much of such language X is better/stronger than Y propaganda is not helpful at all.
I just don't find it particularly productive for full stack web work. API's or other high performance interfaces...great though.
You'd be surprised.
Perl was the glue language of the web and Go is the production language of the cloud.
I'm actually a bit scared to imagine a world in which Go was not created, given how much success I've personally had with it.
Thanks to the entire Go team.
(I don't happen to like either Perl or Go myself! But I think I can see why others do.)
Core philosophy of Perl is to empower programmers with more than one way to do it.
Core philosophy of Go is your coworkers are too stupid to be allowed to have nice things.
The "Go's design and users are dumb" meme needs to die. It's not even a constructive criticism. It's dishonest, insulting, and it's too bad grown adults and professionals can't see beyond it.
I'm not trying to be dishonest or insulting. I've described the philosophy of the language in exactly those terms to Go users, in person, and gotten nods of "Yes, that's right, that's why it works."
I think it's more dishonest to claim that the language designers didn't intentionally limit the language to less than the state of the art as of 30 years ago, on purpose, because of concerns about the mental capacity of users. They themselves admit as much.
The creators have also strongly resisted adding features others consider basic for a decade now, with a variety of nonsensical justifications.
It's a stretch to even claim Go was designed at all. From the very blog post this thread is about, we find this statement:
Russ discovered—that's the right word—that the generality of Go's methods meant that a function could have methods, leading to the http.HandlerFunc idea, which was an unexpected result for all of us.
Go is not exactly a complicated language to begin with, yet the designers "discovered" things about it whilst building it.
Go gets a lot of criticism because it's an empirically very poor language and its designers routinely say absurd things that invite ridicule, like "Go is the language of the cloud" or "We have invented a GC for the next 20 years" or "Go was designed for interns and students who can't handle brilliant languages".
include $(GOROOT)/src/Make.$(GOARCH)
TARG=bin/command
GOFILES=main.go
include $(GOROOT)/src/Make.cmd
The thing I miss most is the netchan. I understand the reasons they got rid of it (https://groups.google.com/forum/#!topic/golang-nuts/Er3Tetnt...) but when it worked, it was fantastic.I'm a polyglot, so before Go, I loved exploring every new language I could get my hands on[0]. I still do, for fun, but Go is the one language that has kept me hooked all this time. It's not for any single feature, or for the community (though that's a great part of it). It's because it's the only language which I feel gets out of the way for me and lets me write powerful, robust, and maintainable software quickly without having to think or struggle against the tools.
For me, Go is like trying to do surgery wearing latex surgical gloves, instead of wearing thick woolen mittens.
[0] Seriously: if you can name it, and there's a working Linux x86_64 compiler/interpreter for it, I've probably tried it.
I have a lot of respect for Clojure, though I don't have much of a use case for it.
At the time I tried it, I was annoyed its semantics for '() and nil - they're sort of a hybrid between how Common Lisp does it and how Java does it. Which makes sense - the Common Lisp approach would be a nightmare to implement on top of the JVM while maintaining interoperability, but as someone whose primary language before that was Lisp, it was a bit weird to try and get used to.
I love functional programming - before Go, Lisp did pay a number of my bills, after all! - but to me it feels more like art than work. It's fun to figure out the most elegant, Lisp-like way to approach a problem. It's fun to convert an arbitrary task into a language-recognition problem and then write the compiler to recognize that language as the implementation to the solution. I get the same feeling from it that I do when I finish a drawing and stand back to look at it. I don't want to touch it, lest I smudge it - I just want to sit back and appreciate the finished result.
But it's a completely different kind of satisfaction that I get from writing Go - there, the fun is in how quickly I can solve a problem, and how confident I am in the reliability, robustness, and long-term maintainability of my initial effort. That's where Go really shines for me, and it's not like the joy of having created an beautiful work of art. It's more like the satisfaction of having built a solid American Colonial house for yourself to live in.
I like them both, but for my professional work, I'll choose Go every time.
Big testament to great interfaces being hugely impactful. For me, the IO and HTTP interfaces are a big part of why Go is so nice to use; the libraries (including std) that emerged around those interfaces and their subsequent interoperability makes everything so coherent.
Congrats to the Go team and their amazing work!
I wish I had more time to take a serious stab at learning it.
Is this lack of freedom a good thing?
Large Java codebases in giant companies are often very poor because:
1. Giant non-software companies often have low hiring bars for their software teams.
2. They are full of bored programmers working on boring software, these people then find ways to make their lives more interesting and kill the time by over-engineering things.
3. These codebases are often very large, old, and have suffered many requirements changes with little or no time allocated to clearing technical debt.
There's nothing in Go that'd make any of these things better. It may superficially appear this way because Go is, in the grand scheme of things, still quite new and hardly used in the enterprise (because it doesn't solve anything better than Java), and as such there aren't any large enterprise codebases written in it. But if you compare the language features, it's hard to explain what would make Go result in better quality software than Java and easy to find things that'd make it worse.
We've had autoformatters before, but they were always customisable things, sparsely used. Go shipping a formatter with the core distribution? Go projects routinely adopting it as a requirement for contributors? One standard format defined from the start?
Knockdown stuff. All those pointless arguments about coding style, gone. All that worrying about how to lay things out, gone. Just run go fmt and move on.
I have now become entirely reliant on rustfmt when I'm writing Rust, and I love it. I just write a total horrible mess, press save and it magically becomes neat and lovely.
I wish I had something that powerful operating in my C# environment at work.
Admittedly, at the moment I also wish my C# environment at work wasn't laden with iron-clad layout rules that the tooling isn't capable of fixing for me. All private members must be after the public ones, but static private ones need to be before the instance ones, and all properties go first regardless of accessibility (although remember the private properties have to go after the public properties). And usings must go inside the namespace definition, in alphabetical order except System.whatever, which all come first (in alphabetical order). And you can't split a function argument across multiple lines unless it's a lambda. Microsoft's C# style guide? What's that and why would we care and no it's not prescriptive enough anyway.
It's enough to make your head spin. Good thing I'm only there for six more days.
Give every language a formatter, as standard, and let's just be done with it.
I know this is super nitpicky, but I like to keep work and personal code completely separate and changing GOPATHs is very frustrating.
With the introduction of `vendor` and software like glide and dep tool, you no longer have to store your sources in `$GOPATH/src`.
Since dep/glide are also required for sane dependency version management, there seems to be no benefit of using `src` over `vendor`.
Without `src`, is there any reason `GOPATH` is still required?
Or have a GOPATH with two dirs like:
GOPATH="~/workgo:~/homego"How would your ideal system look like? What is your use case?
Sidenote if it helps there is a default gopath location if its not defined: https://golang.org/doc/go1.8#gopath
Nothing from outside the repo can effect that build. Likewise anything inside the repo can’t effect the outside.
Compartmentalizing each project makes builds more reproducible and more obvious. If anyone else clones the same repo and runs the same commands, they should get the same result.
I really like Go, it's so nice for server side applications.
export GOPATH=/home/ubercow/project2/
Or even: export GOPATH=`pwd`
When it's time to work on your project just say . source
This seems like an INCREDIBLY minor step to take. It's certainly no worse than using pyenv.I've learned a ton about programming from Go and I'm not sure I would have managed to build the system at all with another language. Go gets a lot of flak for its simplicity, but what it does it does very well. The concurrency model, networking packages, tooling, and simple deployment make it a joy to work with and I owe a lot to the Golang team. Happy birthday!
The general portability and simplicity of the language has made it nice for side-project work.
I've since used go to write a blog engine, several APIs for school projects, and have been working on a scripting language (pisc.junglecoder.com).
> It's worth stating that the language is called Go; "golang" comes from the web site address (go.com was already a Disney web site) but is not the proper name of the language.)
You already have a hugely popular game called Go (WeiQi/Baiduk). It just adds confusion to queries to call the language Go instead of Golang. Even the #go channel on freenode has a disclaimer that it's not about the language. It's like calling your language football.
By this metric, the best programming languages are Perl and Fortran.
Is that true? First time I hear of a dominance of Go in the cloud. (And what does it mean anyway -- any distributed app that runs on the cloud, or cloud infrastructure... such as?)
It isn't. It's like saying Ruby dominates the VM space because Vagrant uses Ruby. Sure there are a lot of orchestration tools written in Go, but look at the actual apps running in the cloud, how many efficient RDBMS written in Go widely deployed? worker queues? full text search engines? ETL solutions? streaming servers? or just actual apps users interact directly with?
It's the "Go is a system language" all over again. It's at best misleading.
is written in Ruby.
The second thing that bothered me was that an edge-case bug in one of my HTTP handlers paniced the app. If that had happened in production while under load, many users would have gotten an error due to a bug in one user's request.
So, serious questions:
- What is the best way to map objects to/from JSON? - What is the best way to map objects to/from a database? - What is the best way to prevent a request from crashing the server and killing a bunch of unrelated requests?
Admittedly, mapping objects to/from database entries is a bit more complicated. There are several ORMs out there or you can role your own.
I've wondered whether a wrapper library could do rule-based field name mapping automatically with Go's reflection facilities (which could be a productivity win), but I haven't really looked at it closely.
I'd recommend using the JSON to generate your struct definitions, in a schema-like fashion. I wrote a tool to automate that process: https://github.com/ChimeraCoder/gojson
I use this as a step in the build system for the projects, which ensures that the definitions stay in sync with the API clients/servers themselves.
If you are doing heavy sql queries, then it might be beneficial for you to use an ORM. There are plently of those out there, so choose one you like. Just create structs for your tables and run your queries.
If you are doing light/moderate sql. Just have an interface for your db calls, wrap your responses in a struct and use json tags for json encoding/decoding.
> What is the best way to prevent a request from crashing the server and killing a bunch of unrelated requests?
I use negroni. And its recovery middleware does exactly that.
Hacker News is about stuff we're interested in, which is not necessarily stuff we get employed to do.
Places lean to some niche or other, and vice versa. Apple places its growing hardware teams in Texas despite new campus in The Valley and all that. Why? Because Austin is very much hardware place.
https://www.indeed.co.uk/jobs?q=golang&l=London%2C+London returns 194 Go jobs for London area
Another option that looks nice is the Buffalo[1]. It's a collection of libraries that are built to play nice with each other, but you don't have to use all of them as a bundle. You can use only the layers you want.
And, I really started digging into the native http support. Go has a lot of really nice things built in and ready to go. Still working on learning what they've got, so maybe I'll end up wanting a framework again at some point. But for now, it's got everything I need for general tasks.
Somehow still no one I know knows what Go is!
I manage servers for an awful lot of developers and, from my conversations with them, I'd be surprised if I could say more than single digit percentage have ever heard of Go.
This site doesn't allow satire but looks the other way when snarky claims are made without evidence. Blanket assertions must be backed up. At least show the problem you were trying to solve and the new solution in your favoured language/tool/framework so it can be judged.
This is how bad ideas and complexity gain traction without scrutiny and push back. People become vested in Ruby and run down php, people become vested in Rust and run down Go, people become vested in React and run down jquery. How comes tools people were using happily just yesterday are suddenly 'completely unacceptable'?
No one who befitted from these tools and languages is going to run them down publicly because they found something better. This is self serving ecosystem marketing at work that HN seems to ignore. It's as if every self congratulatory commentator often seen here was born an expert and short circuited the process of learning, and can use this platform to run down everyone else and their choices.
Meanwhile most commercial JDKs do actually offer AOT compilation, with OpenJDK 9 intoducing it as well.
It fits with the love-it-or-hate-it nature of the whole language.
But their goal was to make it easier for people to do large scale distributed system programming. In that, they succeeded.