42 comments

[ 1.7 ms ] story [ 70.7 ms ] thread
Release notes: https://tip.golang.org/doc/go1.17

Looks like a pretty minor release.

Go 1.17 includes three small enhancements to the language: Conversions from slice to array pointer, unsafe.Add, unsafe.Slice

Function calls now pass arguments in registers instead of via the stack gaining ~5% improved performance.
On AMD64. ARM64 (landing in 1.18) has shown improvements of 10-17%.
Minor on the surface, yes.

Under the hood changing calling conventions is seriously large rework of the compiler and runtime.

Ah yeah, what I get for not reading the entire release notes first :)
Those are just the changes to the language! Many releases have none at all. Keep scrolling for a lot of improvements to the toolchain and standard library, including a couple security changes that might cause necessary behavior changes.
I thought that the 1.17 was going to be the generics release, I guess I was wrong. The 5% performance improvment is very nice, congratulations!
Introduction of generics would need a major version number change. It would involve not just a complier rework, but also a large stdlib rework.
That is not true, generics are and have been planned for 1.18.

They'll be introduced in a backwards compatible way.

https://golang.org/doc/go1compat

Generally, adding features does not break backwards compatibility. Note that ioutil was depreciated while it is unlikely to ever be removed

"The io/ioutil package has turned out to be a poorly defined and hard to understand collection of things. All functionality provided by the package has been moved to other packages. The io/ioutil package remains and will continue to work as before, but we encourage new code to use the new definitions in the io and os packages."

It will never be removed, thankfully.

Even if the new stdlib is 100% backwards compatible (which I think is the goal), it still needs rework to make it use generics where appropriate.
why does the stdlib need to adopt generics? That would break the Go1 promise. They would likely introduce new functions rather than changing existing ones. RE: what they did with the ioutil package
"Originally" they were, but it was bumped to 1.18 (February 2022) a while back.
Thanks, I missed that info.
How far are we from Golang 2.0 RCs? Are they trying to exceed Scala 3's development cycle?

As much as I'd like to use a pragmatic language like golang, I can't live without generics (many folks feel the same way.) Feels like I'm better off learning Rust. Go's loss is Rust's gain.

You learn to work around the lack of generics quite easily. Sometimes this means having to write the same code a few times. But if I look at our entire codebase you're looking at something that impacts less than 1%. I think for most projects the lack of generics is not a major issue.
For 7 years I felt that way. That yeah, generics might be nice-to-have in Go, but if you were really sweating it that it meant you were still thinking in Java instead of Go. But then I switched teams at work and...

> Me: Nothing has ever made me want generics in Go the way that the telepresence2 codebase has made me want generics in Go.

> CTO: Is this because of the problem domain or the incidental structure of the code?

> Me: I'm honestly not sure. I want to say the incidental structure of the code, but I'm not sure how else I'd structure it.

I implemented codegen/template based generics, but eagerly await being able to replace that with actual generics in Go 1.18.

So, I guess the lesson is that it's easy to write off it off when it's someone else having the problem?

Borland C++ for MS-DOS used pre-processor macros in BIDS 1.0, while BIDS 2.0 replaced that hack with templates.

In 2002, Visual Studio T4 was used for generating .NET code shortly after it was introduced.

In 2005, Eclipse EMF was used for generating Java code, eventually Java 5 made that unnecessary.

As you see, that is a path well known for the last 30 years.

Eagerly waiting for Go 1.18, even with CLU like generics.

The funny thing is that in 30 years there will be a new generation of people convinced that nobody needs generics because they happened not to need them in their command line tool replacing a bash script that has grown too large for comfort.
Sadly I have been around long enough to agree with your prophecy turning into reality.
The first implementation of generics is planned for Go 1.18, so no need for a Go 2.0.
# Go 2

In 2017[1] it was decided that the "Go 2" project would be done incrementally adding features in Go 1.x releases, as long as those features can be added in backward-compatible ways, and there will likely only be a actual 2.x release if they need to make backward incompatible changes:

> Once all the backwards-compatible work is done, say in Go 1.20, then we can make the backwards-incompatible changes in Go 2.0. If there turn out to be no backwards-incompatible changes, maybe we just declare that Go 1.20 is Go 2.0. [1]

With that, they developed a formal language-change proposal and acceptance process, and the Go 2 proposals transitioned from being pie in the sky ideas to concrete proposals, and a number of proposals for "go2" features were selected[2] to be included in 1.13. And so in September 2019, Go 1.13 became the first "go2" release[3], the first release since 2012 to include significant language changes.

And so we've been seeing language changes land incrementally in releases for the last several years now, rather than waiting for a "big bang" 2.0 release.

# Development cycle

Go does a release every 6 months, in February and in August. ("But above you said 1.13 was in September!" Yes, it slipped from August to September 3rd.)

# Generics

Generics[4] are currently slated to be in Go 1.18 (February 2022).[5]

[1]: https://blog.golang.org/toward-go2

[2]: https://blog.golang.org/go2-here-we-come

[3]: https://blog.golang.org/go2-next-steps

[4]: https://github.com/golang/go/issues/43651

[5]: https://blog.golang.org/generics-proposal

I may not love the language but I do love this release plan!
> As much as I'd like to use a pragmatic language like golang, I can't live without generics (many folks feel the same way.) Feels like I'm better off learning Rust. Go's loss is Rust's gain.

You can usually have "generics" by way of code generation, or losing type safety. Both aren't perfect but they still work. I wonder, what do you use generics for? Maybe Go isn't suited for that type of work in general.

> Feels like I'm better off learning Rust. Go's loss is Rust's gain.

Or just Java, Go isn't just competing with Rust. Again, that will depend on your problem space.

> I wonder, what do you use generics for?

Check if an element is contained in a slice is the textbook example.

There aren't many productive language discussions that include sentences like "Blub's loss is Floop's gain". If you want to learn Rust, go learn Rust. We call them "languages", but they're just tools we use to solve problems. Use the one that makes sense for you. We use both Blub and Floop; it works out fine.
I feel a bit differently about it. Learning Rust is a longer process, but after it's done, it can do everything better than Go (faster, safer, less code). It can also do things that Go cannot.

People choose Go because they are incapable of making that initial investment. Maybe they know too little and can't wrap their head around the necessary concepts (a CS curricilum should teach one everything that's necessary though), or they know too much and they don't want to learn new things anymore.

I see these programmers as vunerable and confused, and easy to take advantage of. They need something they can feel comfortable and proficient in, and Go provides that. Unfortunately Go is also tied to one corporation and its internal politics.

And so the quality of life od these poor souls is being sacrificed because of someone's strongheaded opinions within their organization. The tragedy is that the Go community is prone to take the words of the Go team as the words of God. And they adapt their mindset to match. So they take on the arguments of the Go developers, and start using them, not realizing that in reality they're arguing against themselves, their comfort and productivity.

Generics, algebraic data types, type inference for lambdas, namespaces, immutability, non-nil pointers, tuples, better error handling, all of these things would improve Go user's lives, even if they don't realize it themselves. But it would be a hassle for Google to add them.

You're being absurdly condescending. Maybe those people aren't lost, but you're just not seeing something they do, or are used to completely different use cases?

I've used and understood most if not all of the languages you might have in mind as being "superior" to Go, Rust wasn't very difficult other than the initial 2 weeks warmup. I've used it for a few months on a side project. It's fun.

And yet I choose to use Go in my day to day 95% of the time.

Go is an insanely practical language. It's also a very productive one, mostly thanks to the ecosystem and people being very practically-oriented instead of bikeshedding on every little detail. Depending on your area of work, it has an extensive ecosystem of libraries too.

And most of all, it's got the best asynchronicity model I've so far had the pleasure to work with. You can see more about this in my recent comment[0].

Yes, it lacks some features, but it's getting there. And wether I agree with the final form of those features or not, I'm happy they're not being rushed.

And yes, like all tools, for some use cases it is a terrible choice.

[0]: https://news.ycombinator.com/item?id=27545031

You just didn't get what I was getting at. Go as a language is fine, and it's OK to like it and to use it.

The problem is that it can't get better, and the obvious issues can't get fixed because any improvements to the language are mired in Google's infighting process.

There were internal voices pointing out a need for generics 10 _years_ ago.

Instead, their PR messaging is convincing people that actually they don't need generics, instead of admitting that the language is incomplete.

My biggest issue with Go is mostly generics really, everything else I can live with it.

Rust's killer domain are kernels, device drivers, high integrity computing, GPGPU, basically domains where having any sort of GC is a hard sale, even if already proven otherwise, or just considered too risky due to timing constraints.

Language features alone don't sell products.

> If a module specifies go 1.17 or higher in its go.mod file, its transitive requirements are now loaded lazily, avoiding the need to download or read go.mod files for otherwise-irrelevant dependencies. To support lazy loading, in Go 1.17 modules the go command maintains explicit requirements in the go.mod file for every dependency that provides any package transitively imported by any package or test within the module. See the design document for more detail.

Wait, does this mean we can import things that themselves import kubernetes without also having to include this huge list of overrides [0] due to the huge list of v0.0.0 imports that k8s then overrides?

Or is that going to take other changes... (like fixing whatever makes k8s import + override v0.0.0)

0: https://github.com/replicatedhq/kots/blob/v1.47.0/go.mod#L11...

1: https://github.com/kubernetes/kubernetes/blob/v1.21.2/go.mod...

> like fixing whatever makes k8s import + override v0.0.0

What needs fixing is the kubernetes.git release process.

kubernetes.git/go.mod "overrides" v0.0.0 not with another version (as you do), but with a local directory, because the sources-of-truth for each of those are the kubernetes.git/staging/XXX/ directories. Because of this, if you're working in kubernetes.git the version number never actually matters, so they just leave it with a dummy v0.0.0. But it does matter if you want to import kubernetes.git!

If you have nested Go modules in one repo like that, the thing to do to keep your importers happy is that whenever you do a release, you `go mod edit -require=NESTED_MODULE@VERSION` to bump the version number to the one you're about to release. This is what we do in Telepresence[1], if only we could get the Kubernetes folks to do it too...

[1]: https://github.com/telepresenceio/telepresence/blob/v2.3.4/b...

From the linked release notes:

> Note that the new conversion from slice to array pointer is the first case in which a type conversion can panic at run time. Analysis tools that assume type conversions can never panic should be updated to consider this possibility.

I'm not worried about updating tools, I'm worried about updating humans that assume type conversions can never panic at run time. This change feels like adding a substantial foot-gun.

> The P521 curve implementation has been rewritten using code generated by the fiat-crypto project, which is based on a formally-verified model of the arithmetic operations. It is now constant-time and three times faster on amd64 and arm64. The observable behavior has not otherwise changed.

This is exciting to see formally-verified Coq code being pulled into Go.

https://github.com/mit-plv/fiat-crypto