Hacker News new | past | comments | ask | show | jobs | submit login
Go Turns 15 (go.dev)
88 points by zdw 22 days ago | hide | past | favorite | 26 comments



I've become a lot more positive on Go over the years. I tried it a few times starting from when it was released and always found some roadblocks that aggravated me enough not to keep going except for toy projects. They've pretty steadily been removing those even if they keep others, but on the balance the benefits of the language outweigh the remaining drawbacks for me when I'm looking to make something where Go shines such as when a single static binary is a benefit. Overall I still prefer to work in Clojure, all other things being equal, but Go is a nice tool to add to the belt.

A huge one for me was the lack of a reasonable project structure - they expected all your Go code to live in one huge directory nested deeply by the import path. It probably worked fine inside Google due to their reputed giant monorepo but it was aggravating to me who has a (much more common, I think) `~/Code` directory with a bunch of projects in it, one level deep. They fixed this along with managing dependency versioning with `go.mod` and `go.lock` files some versions ago and it completely eliminated the problem for me.

Generics was another one. I don't love generics but there are some classes of code for which a lack of generics only leads to pain. It's nice that they finally added them.

One thing that hasn't changed is their amazing commitment to not breaking existing code. It's really nice to pull up an old project, update the version in `go.mod` (or add one if it didn't exist) and things Just Work™ along with whatever extra benefits you gain from the version upgrade. They clearly did extensive research to avoid breaking even what I consider extremely non-obvious and borderline erroneous behavior (that for loop thing) and did it in a way that makes sense.

Their standard lib is good, and pretty well documented. I can often get what I need without having to resort to pulling in a dependency or writing it myself. That's handy.

The VSCode support for it is top notch and also Just Works™ in my experience. There's no REPL of course but the debugger can fill a similar role aided by the extremely fast compilation time.


We do have to acknowledge Go's significant influence on language tooling. I'm not sure my own joy in Rust's tooling would be in the same place at all if we didn't have Go there shipping package management and autoformatting out of the box. Autoformatting - what a revolution in creating a language community where that's a standard, required part of the workflow! What an entire class of pointless arguments that's helped to eliminate. Marvellous.

I'm glad I turned down a job working in Go though. Whenever I read some open source tool's code to find out what it does, anything in Go seems unnecessarily verbose and extremely simplistic. It's all the design principles of Java that I don't like, but more of it. Not my style, but an undeniable positive impact elsewhere also.

And to some extent the idea that we can have modern languages with modern tooling which compile to native code and run really fast is much perpetuated by Go, and this is highly valuable in a world where far too many things are written in JavaScript and bundled with a web browser to render them because that's "easier".


> It's all the design principles of Java that I don't like, but more of it.

I'm curious what you're referring to there. I think of Go as the "anti-Java". Where Java has "org.apache.commons.httpclient", Go has "net/http". Where Java has stuttering like "final Logger logger = LogManager.getLogger();", Go has "logger := log.New()" (and no log4j vulnerablity). A typical "simple" app in Java puts files in "src/com/username/simplewebapp/subdir", typical Go project structure is to put files in just "subdir", or even just in the root dir. And so on.


Tried to contribute to a Go project a few months ago and got bitten by https://github.com/golang/go/issues/67296 due to questionable doc quality. I was pretty disappointed to find that natural sort isn't builtin since Go was the Unicode language in my mind (Go runes, made by some Plan 9 thus UTF-8 creators).

Go has a lot of good points, but I immediately felt "dirty" when using it. Like that time when I tried to wrap a closure variable over itself ("my_closure = new closure calling my_closure") and needed to use a temporary variable because closure captures are always by reference: if you want to build abstractions, you got to think them better; as it stands, this is the worst of both worlds I know (C++ makes capture type explicit and customizable, Common Lisp was designed by wizards who knew what to do cf https://www.tfeb.org/fragments/2023/02/22/how-to-understand-...).


We may have different definitions of 'temporary variable', but you don't need what I would think of as a temporary variable to make a self-calling closure:

     toCapture := 99
     var myClosure func() int
     myClosure = func() int { return myClosure() + toCapture } // nonsense
     myClosure()
It would be nice if Go would just allow the use of function definition syntax inside functions, though. Seems like a small and non-breaking change that could easily be made.


One can sort of get a non reference capture, by passing the same name as a argument; but yes it would be nice if one could somehow say capture by value.

    foo := 1
    closure := func(foo int) func() int { return func() int { return foo += 1 } }(foo)

    x := closure() // 2, w/o altering outer foo
If not something like the above, I'm not sure what you're trying to express. Possibly what 'foldr' suggested, or that with mine such that one passes in the initial closure function as a argument?


> One thing that hasn't changed is their amazing commitment to not breaking existing code.

Er, are you sure?

* https://x.com/zigo_101/status/1856173025839960333

* https://x.com/zigo_101/status/1854918262523621805

* https://x.com/zigo_101/status/1854213142177624169


The loop variable change doesn't break existing code because the new behavior kicks in only if you update the Go version in go.mod.


It is not that simple.

For some Go scripts without go.mod involved, Go 1.22.n toolchains break backward compatibility for sure. Go core team have admitted this but refused to fix it for Go 1.22.n toolchains: https://github.com/golang/go/issues/66092

And, even for the Go code with go.mod involved, there are some behavior change cases which will be not detected in time when you update the Go version in go.mod. Please read https://go101.org/blog/2024-03-01-for-loop-semantic-changes-... for such cases. Now, no tools can detect some of the cases.

The more serious problem than behavior changes is, with the new 3-clause "for;;" loop semantics, it is more error-prone to use loop variables. Making the semantic change (on 3-clause "for;;" loop) might be the worst decision made in Go history.


You've made your point about the new for loop behavior many times. As others have also pointed out, people just don't agree with you about this. They're not going to suddenly start agreeing if you keep posting the same thing over and over again. (Now that I type this out I'm sure I could stand to learn the same lesson on a few topics!)


The facts in my comments are for the people who need them. Maybe you are not one of them. But then why do you so care about it?


How many go scripts nowadays come without go.mod? I would hazard a guess of only 0.00001%. And since it’s without go.mod, it shouldn’t be used anyway.


First, Go Official has never expressed the same opinion as you officially. In fact, the "go run GoSourceFilesWithoutGoDotModFile" command is still supported in 1.22 and latest Go toolchain versions.

Second, the idea that rarity deserves to be ignored is flawed logic and shows a lack of respect.


how obnoxious can you be with constantly reposting these


wow! I thought you were exaggerating but on a quick glance, their presence in HN is mostly about criticizing Go.


I wrote many Go articles praising Go: https://go101.org/

I am neither a no-brainer Go hater nor a no-brainer Go lover. Good is good, bad is bad. All my articles/posts are based on facts.


I only post facts. :D


You need to stop doing this. It's now at the point where you're derailing every other Go thread with this. Quite frankly, it's becoming obsessive.

I'm not saying you can never mention this, but you need to stop derailing every other Go thread. In many cases you post it more than once (two here). In other cases it's bizarrely off-topic (e.g. the Russ Cox resigning thread).


> You need to stop doing this. It's now at the point where you're derailing every other Go thread with this.

This is not true. I haven't posted any comments in many Go threads. I only comment when it is related.

And most gophers have not been aware of the problems of the new semantics of 3-clause "for;;" loops and it looks Go official don't have the intention to let them know. So I do it. I think this is good for the Go community.


Go is one of those languages you get shit done. Its fast, it compiles fast and is type safe enough. It has a rich stdlib and comes with pretty much all you need (formatter, lsp, testing).

Overall Go is really good, but not perfect. A few minor things are missing (like adts/pattern matching). But i want to belive that go will one day have them!

HBD Go!


This language has been a huge boon to our field: simple to learn, easy to support, capable of excellent performance, delivering long term compatibility for production code, and with one of the fastest compilers around.

I think people now forget how much impact Go’s command line tooling has had on user experience for developers. Everyone copied it. I was skeptical of the language at first but have worked mostly in Go for the last 11 years and it has been a joy. Happy 15th, Go!


> So much has changed since Go’s 10 year anniversary,

Discussion then: https://news.ycombinator.com/item?id=21483933


> Go 1.22 made variables introduced by for loops scoped per iteration, rather than per loop, addressing a long-standing language “gotcha”.

This does fixes the "for-range" loop gotcha, but brings several gotchas to the 3-clause "for;;" loops:

* https://go101.org/blog/2024-03-01-for-loop-semantic-changes-...

* https://github.com/golang/go/issues/66156

* https://x.com/zigo_101/status/1856173025839960333

* https://x.com/zigo_101/status/1854918262523621805

* https://x.com/zigo_101/status/1854213142177624169


To me, it's not a gotcha. As the github issue discussion notices, loops where the semantics depend on the identity of the loop variable to remain the same over the 3-clause loop iteration is exceedingly rare. I'd also say it's contrived and should not pass a code review.

Funnily, a 3-clause loop in Go (and in C) is actually a reduce(), where the loop variable's value, possibly touched by the iteration, is then directed back to the next iteration. This makes it more powerful (e.g. can traverse graphs, etc), but also more complex than it looks in the case of an integer and increment.


Simple wins.

Golang and Rust were once peers, both new languages at around the same time.

This is why Golang has gone mainstream and Rust remains niche.


go is the boring language that gets stuff done, perfectly suited for that class of people who care only about outcome




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

Search: