Live data from Hacker News

Go 1.13 Release Notes

golang.org

161–170 of 264 posts

Re: Go 1.13 Release Notes

#161

Earlier quoted context omitted.

For the threading difference, do you mean that Rust needs 'normal' threads plus async/await support, but Go can just lean on its built in concurrency support for both cases? i.e. Go threads instead of explicit async style code.

Your sentence implies that Go green threads can do both of what 1:1 threading and async/await can, but it's more complex than that: there's a tradeoff between the simplicity (only one concurrency primitive) and the capability of the said primitive: - with it's M:N model, Go cannot really do FFI efficiently, while both 1:1 async/await have no problem with that in Rust. - goroutines are cooperatively scheduled, while O…

The reason cgo is (relatively) slow is small stacks, not M:N threading.

Small stacks (and M:N threading) are needed to efficiently implement tens of thousands of goroutines.

CGO is slow mostly because it needs to switch to a larger stack when calling a C function.

It's a trade-off.

A different Go implementation could make Goroutines map 1:1 to threads and have fast cgo calls at the expense of slow goroutines.

Rust is not exempt from those trade-offs. They chose fast FFI and smaller runtime. They paid with slow threads.

Async/await promises to be the best of both worlds but it comes at a cost of great complexity, both for the programmer and the implementor.

At the end of the day under the covers it's just threads that need to be managed in a complex and often invisible way plus a complex rewrite of your straightforward code into a mess of a state machine.

I can confidently say that learning to use goroutines took 10x less time than learning async/await in C#.

I understand goroutines better than I ever understood async/away.

Re: Go 1.13 Release Notes

#162
post #76

Earlier quoted context omitted.

I know. The question is, why does it need a colon? It seems completely superfluous, from a syntax perspective.

It's to avoid typos. Imagine there is no colon. When you type foo = 3 fooo = foo + 1 Did you mean to create a new variable called `fooo` or was it a typo? Did you mean this: foo := 3 fooo = foo + 1 // oops, typo found at compile-time or that: foo := 3 fooo := foo + 1 // Yep, new var, everything is ok

Why not just have

var foo = 1

Re: Go 1.13 Release Notes

#163

Earlier quoted context omitted.

Have you tried async? I find it much easier personally to reason about and debug than channels, and is perfect for IO-bound problems. If you really like channels, note that Python 3.9 will have sub-interpreters and channels as well: https://hackernoon.com/has-the-python-gil-been-slain-9440d28...

Goroutines are quite a lot nicer than async for a few reasons. Firstly, there are no “forgot to await” errors, secondly there is no need to worry about some library making a sync call way down the call stack and therefore blocking your event loop, and thirdly goroutines can use all cores on a CPU to parallelize CPU intensive tasks, which means you don’t block the event loop unless you really are out of CPU. Blocking…

A lot of what you describe is for CPU bound problems, most of the problems I face personally and the the problem, in particular, the parent mentioned are IO-bound. Async in Python is a near-perfect fit for this kind of problem space and is really easy to reason about and debug as you can step through and debug one line of execution at a time.

Re: Go 1.13 Release Notes

#164

Earlier quoted context omitted.

Goroutines are quite a lot nicer than async for a few reasons. Firstly, there are no “forgot to await” errors, secondly there is no need to worry about some library making a sync call way down the call stack and therefore blocking your event loop, and thirdly goroutines can use all cores on a CPU to parallelize CPU intensive tasks, which means you don’t block the event loop unless you really are out of CPU. Blocking…

A lot of what you describe is for CPU bound problems, most of the problems I face personally and the the problem, in particular, the parent mentioned are IO-bound. Async in Python is a near-perfect fit for this kind of problem space and is really easy to reason about and debug as you can step through and debug one line of execution at a time.

Only one of those problems is CPU. The others are type system and IO issues, and they happen in IO bound services too.

Re: Go 1.13 Release Notes

#165
post #149
post #120

Earlier quoted context omitted.

Personal opinion: no. Go's concurrency is hard to control or monitor, and it's hard to make higher level abstractions that are both safe and convenient. It's of course possible, but the tradeoffs are rather severe. Go's concurrency shines best in short-lived single-purpose processes, which is a near perfect fit for CLI tools. When you don't care if something gets abandoned or fails to make progress and can just ctrl-…

Could you expand on what you think is hard about the concurrency in Go? (And perhaps give an example of a language that makes it easy/easier?)

Not the OP, but if you’ve ever had to write 100% fault tolerant concurrent Go code, you find yourself having to add a lot of monitor-recover-restart “boilerplate” that ends up being quite complex, depending on the task at hand.

It helps if you follow certain principles like making your concurrent tasks idempotent etc., but Go doesn’t force you to write things that way, so it takes a bit of remembering each time.

If the task is relatively simple, you end up writing a lot of concurrency infra for a little bit of concurrency, which can become frustrating if you’re doing it for the Nth time.

It sounds like a problem that’s ripe for abstraction, but it turns out that it’s quite hard to build abstractions that get all the trade offs just right for each case. There’s some worker pool style libraries out there, but if you care about performance you can usually eke more out by writing a custom solution.

As for alternatives, I have heard that erlang has a better story for this, because of the inherent restrictions of the language, but I haven’t used it much.

In my experience, Go gives you enough rope to make this task “merely annoying” (rather than impossible or astoundingly challenging) without giving you enough to truly hang yourself with. You can get really tangled up though :)

Re: Go 1.13 Release Notes

#166
post #161

Earlier quoted context omitted.

Your sentence implies that Go green threads can do both of what 1:1 threading and async/await can, but it's more complex than that: there's a tradeoff between the simplicity (only one concurrency primitive) and the capability of the said primitive: - with it's M:N model, Go cannot really do FFI efficiently, while both 1:1 async/await have no problem with that in Rust. - goroutines are cooperatively scheduled, while O…

The reason cgo is (relatively) slow is small stacks, not M:N threading. Small stacks (and M:N threading) are needed to efficiently implement tens of thousands of goroutines. CGO is slow mostly because it needs to switch to a larger stack when calling a C function. It's a trade-off. A different Go implementation could make Goroutines map 1:1 to threads and have fast cgo calls at the expense of slow goroutines. Rust is…

> Small stacks (and M:N threading) are needed to efficiently implement tens of thousands of goroutines.

Tens of thousands of threads are no problem with 1:1 threading on Linux.

> They paid with slow threads.

I would not call 1:1 threads "slow threads". If they were slow, then the 1:1 NPTL would have not defeated the M:N NGPT back in the day when this was being debated in the open source OS community.

> complex rewrite of your straightforward code into a mess of a state machine.

The entire point of async/await is that you don't have to do a complex rewrite of your straightforward code. It remains straightforward, and the compiler does the transformation for you.

Re: Go 1.13 Release Notes

#167
post #89
post #52

I started poking around and noticed that Go 1.13 now defaults to the Golang Proxy to fetch modules. This means a proxy, governed by the Google Privacy Policy, is now capturing everyone's module usage by default. Unless you change settings this includes proprietary/corp stuff. https://codeengineered.com/blog/2019/go-mod-proxy-psa/

> This means a proxy, governed by the Google Privacy Policy, is now capturing everyone's module usage by default. No surprise there, was even called a 'privacy nut' on the neighboring Android 10 thread for highlighting the nature of Google's 'privacy' stance. So essentially they turn on tracking / analytics on by default for module usage without consent or any notice except for the lengthy privacy policy. This remind…

> "without consent or any notice except for the lengthy privacy policy"

There's also there in release notes:

> "The GOPROXY environment variable may now be set to a comma-separated list of proxy URLs or the special token direct, and its default value is now https://proxy.golang.org "

Re: Go 1.13 Release Notes

#168

Earlier quoted context omitted.

First programming language that I've had to read and understand a privacy policy to use.. and consider that it may change in the future. The idea that the language I'm programming in now reports anything back to google is distressing.. and I say that as someone who has been programming in Go for about 7 years. What right does google have to collect usage information from modules hosted on github (or elsewhere)? I che…

> This "feature" should have an option to disable it.. at the very least. You should be able to. It's not the ideal solution (or recommended for most use cases), but you can by setting GOPROXY=off. GOPROXY=direct will force it into its previous behavior. The same should be true for the checksum DB with GOSUMDB=off. I don't remember specifically and can't find the page its options were documented on. Also look at GOPR…

IMO, using an environment variable for that is not robust. If the environment variables have been cleared (for instance, due to "su -" or similar), or if they have never been set (for instance, because you just checked out the code on a new machine and forgot to configure the environment variables there, or because you did remember to configure the environment variables but forgot that startup scripts do not take effect on an already running shell), the defaults will apply. Using a configuration file within the source directory would have been more robust.

Re: Go 1.13 Release Notes

#169
post #161

Earlier quoted context omitted.

Your sentence implies that Go green threads can do both of what 1:1 threading and async/await can, but it's more complex than that: there's a tradeoff between the simplicity (only one concurrency primitive) and the capability of the said primitive: - with it's M:N model, Go cannot really do FFI efficiently, while both 1:1 async/await have no problem with that in Rust. - goroutines are cooperatively scheduled, while O…

The reason cgo is (relatively) slow is small stacks, not M:N threading. Small stacks (and M:N threading) are needed to efficiently implement tens of thousands of goroutines. CGO is slow mostly because it needs to switch to a larger stack when calling a C function. It's a trade-off. A different Go implementation could make Goroutines map 1:1 to threads and have fast cgo calls at the expense of slow goroutines. Rust is…

> It's a trade-off.

Yes, That's exactly my point.

> I can confidently say that learning to use goroutines took 10x less time than learning async/await in C#.

It's a matter of preferences, I've always preferred async/await to threads because you don't need to juggle with channels and you're way less likely to cause a deadlock.

> it comes at a cost of great complexity, both for the programmer and the implementor.

Is that really harder to implement than a M:N runtime like Go's?

> The reason cgo is (relatively) slow is small stacks, not M:N threading.

You're picking nits here. Without small stacks there would be no point using M:N threading in Go…

And Cgo is not only relatively slow: most of the time it is slow enough to destroy all performance benefit of calling a FFI function. It's a pretty big deal.

Re: Go 1.13 Release Notes

#170
Looking at the release notes:

> Go 1.13 now requires macOS 10.11 El Capitan or later; support for previous versions has been discontinued.

> Go 1.13 now requires FreeBSD 11.2 or later; support for previous versions has been discontinued. FreeBSD 12.0 or later requires a kernel with the COMPAT_FREEBSD11 option set (this is the default).

Sounds like they're still using syscalls directly on those platforms. Is Google ever going to admit that it's broken by design, because userspace apps on those platforms (outside of the base system, which is tightly coupled to the kernel) are not meant to be calling into the kernel directly directly, and should do everything via libc and other userspace libs that wrap syscalls?

Post reply on HN