61 comments

[ 4.9 ms ] story [ 127 ms ] thread
This page was readable until my browser finished downloading the web font, at which point it became impossible to read.
On the plus side, its static nature meant that for me the page is fully readable while it is crushed under the weight of Hacker News' hug-of-death. It took over a minute to load that PNG on the side, and I think it will be trying to send me that font for quite some time.

I forgot how snappy the internet is when you keep it simple.

(comment deleted)
> every object is a member of the empty interface

There are no objects in Go, given that Go is not an object-oriented language... oops! (pun intended)

(comment deleted)
What requirements does an object have to fulfill in your opinion?
The word "object" predates OOP. I think the original meaning roughly equates to what we call a value today.

In OOP languages the objects contain the subroutines (methods) hence orienting the programming towards the objects.

Do the more pedantically inclined have a better definition?

If you're having trouble viewing any content on the page, click the stop button in your browser.

Ironic domain name.

I've written a basic web server which simply pulls up CSS/HTML and manages a mongoDB about 16Gb as well as another for users. I found that overall Go is extremely manageable and the whole server and db management requires less than 500 lines of easy to read code with comments. I agree with the author for the most part, however I would like to say that I do not like the error handling.. Not really a big deal, the rest of the language makes up for it, just thought I would share my opinion.
Currently working with Node.JS and we want to introdcure Go in some new modules. Have 3 major concerns;

- Lack of Generics. I know this has been beaten to death but after using a dynamic typed language all this time, it is even more painful.

- Weird dependency management. No way to lock dependency versions, even if I fork something and depend on it, nested dependencies can fuck up at some point. We need something like NPM to manage our dependencies in a sane way. Importing from live git paths seems like the worst possible solution to this. And there seems to be no widely accepted 3rd party package manager.

- Google... At some point, I'd expect the compiler to require a Google+ account to enable optimizations. /s

> Importing from live git paths seems like the worst possible solution to this.

Then don't do it. Check your dependencies into your repositories and update import paths.

What happens when the dependencies have bugfixes or security flaws? Why is it better to spread the responsibility for updates over all Go authors instead of to the authors of the libraries in question?
You make an explicit, knowledgable decision to update the dependency, like you should be doing with all software in a production environment.
Why is this supposed to involve tons of stupid stuff instead of adjusting a version number accordingly?
> What happens when the dependencies have bugfixes or security flaws?

Copy the new version into the repository, run the import rewriting script and check it in.

> Why is it better to spread the responsibility for updates over all Go authors instead of to the authors of the libraries in question?

Because you want to have full control over your dependencies. What if the author introduces a breaking change or removes the repository from the internet? Do you want to risk your business by being at the mercy of someone else's repository?

What about when the library you want to use has a non-compatible license for distributing it with your source code?
(comment deleted)
Update them when you want. Just like you would with a package manager. If you need to stay up to date, then have something monitor their commit logs.
Checking dependencies into my repositories is worse. It hugely increases friction for upgrades (which means fewer people will do it) and pushes monitoring for updates down onto the consumer rather than the maintainer (which means some people will forget and get owned).

This is the problem that Maven, RubyGems, etc. have fixed for so very long that I find it really hard to take Go seriously when this is floated as a solution. And that seems to be a regular occurrence in Go: the willing championing of bad but "simple" solutions (error codes as far as the eye can see!) under the mistaken assumption that things are complex just to be complex rather than that they're complex because they solve a bigger problem.

> It hugely increases friction for upgrades

I can imagine a script that's just a few lines that downloads go-gettable dependencies and updates import paths. You run it at exactly the time you want to update.

> have fixed for so very long that I find it really hard to take Go seriously when this is floated as a solution

By a large margin, I spend the least amount of time configuring my Go packages for release than for any other language.

I can "imagine" a lot of things, too, or I can change one number in a pom or a Gemfile. Because the infrastructure is both predictable and standardized. (And doesn't require barfing your dependencies' changes into your source tree to do it. Funny, that.)

"Write a script" is a poor solution for an endemic problem.

It's not an excuse. As I said, I spend much less time configuring Go packages than I do for packages written in other languages.
Your claim strains my credulity to the snapping point. Please explain how manual operations are faster (and no more error prone than a transitive dependency solver).

Bear in mind that it is a one field change in a Gemfile or Composer or Maven/SBT/whatever-Java.

Bundler and "go get" are an apples/oranges comparison. Gems fetched through bundler are hermetically sealed libraries that live in their own little secret area of the filesystem; when you add a gem dependency to your project, you're extending the platform that you're building code on.

Golang's "package" system works more like C's than like Ruby's: when you build a program out of libraries, you have the source to those libraries in a well-known highly-visible place in your build environment.

Think of Golang's package management as a refinement of the "codebase/<package>/third-party" idiom in C, and not as an npm/bundler competitor. Golang third-party packages don't work like gems. They are raw code that you build as part of your application.

You could build an npm-alike for Golang; I'm not sure how widely used it would be. I like having my third party deps laid out in my repo and easy to read/patch.

You can argue that the C third-party idiom is worse than Rubygems, and reasonable people can disagree, but I've had a lot of experience in C (I started my career as a C dev) and a lot of experience with Ruby, and gems have caused me more problems than third-party deps ever have.

"You could build an npm-alike for Golang;"

Expanding on this --

There are quite a few dependency management packages for Go already that mimic various other ecosystems, usually written by people who just came to Go from those ecosystems. I can't recommend any because I don't use them because like tptacek I would rather just use a simple repo layout system.

Yeah, I know the differences--I'm using it right now (though I didn't realize it was actually transitive, my bad). I'm straight-up shocked that you say you've had more trouble with gems than source imports; my experience is that it just works (though I have more experience with Java/Scala in Maven than Ruby).

I spend most of my time these days in C++ (writing a game), where there's likewise no package management to speak of, and dealing with the slough of git repos (except when it's hg or svn, because reasons) where I have to go find which ones are updated (and then, how), sucks. It's opaque and stupid and takes time out of my day that could be better spent thinking or writing code or hitting myself between the eyes with a hammer. My favorite dependencies in C++ are ones like Boost that I can just get out of Homebrew as a library and come with release notes. (That's rare enough in C++. And maybe I just pick better Java dependencies, but I pretty much always know what changes between Guava 13.0 and Guava 14.0 without vgrepping a bunch of files. Or compiling the world.)

This is poking me in a sore spot right now because, as it happens, I'm stuck modifying a client's former consultant's pet Go project right now, written in it because trendy. Stuff is broken in some of his pulled-in dependencies, so I've been trying to update them while actually understanding them which means having my head in vimdiff all day. It's making me want to set fire to things and I'm sorely skeptical of claims that this is easier or takes less time for...well...anybody.

When I add a foreign package to my third-party tree in a C program, I know every time I build the system exactly what version of the code I'm getting. On larger, longer-term projects I've worked on, we've gone through pretty elaborate effort not only to package the third-party code along with our own, but also to carefully manage what versions we're using while hiding that detail from the actual program (so that, for instance, version numbers don't infect the #include directives in the source code). Golang's package system does a good job of streamlining this process, so that as long as you don't try to use it like Rubygems, you can create a reliable build environment for an important program with little effort.

Idiomatic bundler, on the other hand --- and, just take my word for it that we've seen a lot of different teams Gemfiles --- treats something like "haml" or "eventmachine" as something akin to a system dependency; versions, when specified, are often fuzzy, like "anything from 1.1.0 to 1.1.9 is acceptable". Ultra-specific versioning in Gemfiles is brittle; a "bundle install" on a mostly-rigid Gemfile can be expected to routinely fail as one gem's dependency on another fails a constraint in the file.

There's an upside to the Bundler mechanism, which is that it's very easy to use and doesn't require you to think about the actual code. In fact, Rubygems even hides cross-language dependencies, so that you can easily use libraries that happen to be native C code without even having to know that you're bridging. But there's a downside too, which is that it's opaque and, like I said, brittle.

Basically you have to decide whether tracking your upstreams is more important than having a deterministic build. The C programmer in me is obsessed with deterministic builds, and Golang appeals to the C programmer in me, not the Ruby programmer.

Again, it's totally legitimate to complain that there isn't a widely-supported npm-alike for Golang. I don't necessarily want one of those, but I can see how a competent programmer would! I'm just saying that it's not reasonable to compare "go get" to npm; they aren't systems with the same goals, even though they sort of look like they are.

Have you used the `go` tool before? `go get` handles transitive dependencies. You use that to download your dependencies. From there, it's trivial to check them into your tree and update the import paths.

> Please explain how manual operations are faster

I said that I spend less time managing package trivia for my Go projects than for any other package. It's not like I spend a lot of time on packages for other languages anyway, but you told me my approach "increased friction." But this is contrary to my experience.

It's not like I have a huge problem with how other languages do things. Or even that I think the `go` tool is better. I just know that it works well. So I'm trying to share that experience for people who can't imagine how it might work well.

I'm not the OP you're asking a question of, but agree with the OP's position.

In my experience the manual operations required by Go (basically just doing a git/mecurial fork into my own repo and git/mercurial updates as desired) may not be "faster" in the sense of requiring less keystrokes or whatever your measurement is, but it is more predictable and understandable, and not too much "slower".

More complicated dependency management systems are great when they work, and then suddenly a huge pain in the ass when they fail in some edge case, the Go way of doing dependency management might require a very tiny bit more effort but pays that off by being much more transparent.

Give up ... that person basically lives on HN/other sites to preach his opinion of Go being the best thing ever as the absolute truth.

Nothing you can say will change his stance even a single inch.

(Yeah. Go's dependency management is so great that people keep writing dozens of wrappers/extensions/replacements. sarcasm)

>I can imagine a script that's just a few lines that downloads go-gettable dependencies and updates import paths. You run it at exactly the time you want to update.

And I can imagine an CSP implementation for C. Should we ditch Go then?

A CSP implementation for C is likely large and complex.

A shell script that runs a few `sed` commands isn't.

You don't actually import from live git paths. You import from your local filesystem ($GOPATH). The compiler doesn't care how code gets into $GOPATH.

A single tool, "go get", pulls code directly from 3rd parties and puts it in $GOPATH. If you're uncomfortable or frustrated using "go get" there are a number of 3rd party options.

I think you may have responded to the wrong comment...
> No way to lock dependency versions, even if I fork something and depend on it, nested dependencies can fuck up at some point.

Just copy the dependencies into your repo and adjust the import paths. If necessary, flatten the dependencies of dependencies.

Is it possible to depend on a named branch on a remote git path? Because, with some sensible conventions, that would be a suitable way to manage dependencies.

(i.e. if you change your major version, start a new branch. if you change your minor version, start a new branch but continue to update the old one also. Actually, without tool support, that's going to get painful, but the idea is sound and requires only local tooling.)

Tags are probably more sensible for this - tag major versions and then people can specify what tag they want.
W/o generics you lose two things:

1. Type safety 2. Convenience

(1) is certainly no worse than a dynamic language, where you don't have type-safety anywhere. (2) doesn't seem that bad to me. You'll write code like this:

  x := customStack.Pop().(SaysHello) // error here if x isn't a member of the interface SaysHello
  x.Hello()
As opposed to a dynamic language:

  x = customStack.Pop()
  x.Hello() // error here if x doesn't define hello
Disclaimer: I've just poked at Go a little bit. I'm thinking about trying it out as a replacement for some Python code I have.

Further disclaimer: As a C++ programmer back in the day I used to make a lot of fun of Java for not having generics (it's had them for a long time now, of course). Lately I've been doing Objective-C (where the situation is like Go, but worse -- no generics nor interfaces; it's all just dynamic), and I've been surprised at how not having generics is Not As Bad As You Might Think. It's basically equivalent to a 'dynamic' language.

You only lose type safety if you're writing generic containers. If you don't need a customStack or something similar you'll be fine.

While I think it's good to know how to write containers, and how they work, how frequently do you really need to write a custom container? What's wrong with the built in ones (provided they exist)?

Yes, didn't mean to imply you lose all static type safety -- you're still way better off on that front than in a language like Python or JavaScript. Basically, if you're happy with a dynamic language, Go makes things better most of the time, but sometimes you have fall back to dynamic checking, because of the lack of generics.

Custom containers: Well, it's definitely true that you can get pretty far with just arrays and hash tables -- which Go special-cases! -- but you're probably gunna want something fancier eventually...

I use go occasionally for minor projects, and I have learned to live without generics. In a couple of projects I ended up implementing $myproj/types which exports all the data structures I want. At that point adding the types.TypeName.Min()/.Max()/... becomes natural. It's already effectively a custom struct, so I have no problem writing the helper functions to deal with them.

Heck, I used to do that in C all the time anyway.

However... The dependency management is my pet peeve #1. I see no problem pulling dependencies from external repositories and building them locally. That practice spans back to at least BSD ports. What I dislike is the fact that I can't specify the version or commit I want to depend on.

I find that the current implementation for "go get" assumes everyone is either a hard-core hacker, always living on the edge (and sometime pushing it) - or they have a full-fledged internal repository infrastructure in place to deal with all the mirroring and continuous integration needs. Go decides internally which revision to checkout and build, using a priority list of hardcoded tag/branch names. If those are not available, it defaults to master:HEAD, /trunk or whatever equal alternative is supported by the underlying SCM. You can not specify "I want to use _this_ version, period" which is a crying shame.

I understand that internally Google doesn't use go get at all. They have their own mirrored repos for everything they need during their builds. Understandable. But ignoring the well-established practice of user-specified upstream component versions is just rude. It forces some "makes sense only in very large organisation" type of practices down the developers' throats.

>Heck, I used to do that in C all the time anyway.

Not a very encouraging notion, considering the issue is quite trivial, solved in 200 other languages, and it's 2014 already.

tl;dr: A quick recap of Go's basic features, also the author likes them.
I had to change the font because the file wasn’t loading...

I'm not sure if there were any confessions. It was basically a "hey, you should try out Go. Maybe. If you want. I like it…" kind of post.

This isn't loading at all for me for some reason. I get 13 bytes and it hangs.

edit: I found the fulltext archived elsewhere on fullhn. This honestly just a listing of Go features and there's no "confession" to speak of anywhere. It seems like the OP would like Erlang.

Site down. Hope he wasn't confessing he wrote his server with Go, because his server sure can't handle load...
Do not work for me too. Amazing the site name is "not broken".
No, he was "confessing" that he liked Go and thinks it's pretty nifty. Not much of a confession...
Hmmm... I was expecting a more controversial article. Basically the author likes Go and gives a brief list of features. (Not that it isn't a good article but for some reason the title set my expectations at the wrong level).
notbroken.org website is broken
I have been reading good things about Chicken Scheme, which compiles to C. I am debating between Go and Chicken for a SaaS startup. Go seems to be the future favorite language for server development, but I read pg's essay "Beating the Averages" and am attracted to Lisp. (And I love Emacs!) Does anyone with experience in these languages have any thoughts?
This isn't really a "confession"... just someone gushing over a programming language in a terrible looking font.