Live data from Hacker News

Conc: Better Structured Concurrency for Go

github.com

111–120 of 162 posts

Re: Conc: Better Structured Concurrency for Go

#111

Earlier quoted context omitted.

It's fine to dislike Go's philosophy on error handling, but in order to save you and your co-workers a lot of headache down the road, I'd recommend you just use another language. This is not something you want to do in Go and very few folks who program in Go would be happy to work with that style of code. In case you actually are interested in Go's take on stack traces: You are intended to annotate your errors so you…

Do you suggest me to annotate my errors with "file:line" strings? Do you suggest me to grep source files with error messages to deduce stack trace? Because that's what I'm doing right now when I have to deal with stacktrace-less errors and it's not pleasant.

> Do you suggest me to grep source files with error messages to deduce stack trace

Yes, that's common. Perhaps a gopls search engine for error messages would be useful?

Re: Conc: Better Structured Concurrency for Go

#113

Earlier quoted context omitted.

Because people make mistakes?

Classic Go programmer. This is why I use rust B) (joke)

Joking aside, you could clearly plot the probability of running into a runtime error by programming language.

Of course, a language with less runtime errors is a far cry from being a panacea. Avoiding runtime errors is not the same as avoiding all categories of bugs. And while I personally prefer stronger type systems - they definitely come with increasing levels of cognitive cost.

But I still feel that the type-safety vs. runtime trade-off is more often ignored, underestimated or undersold than it is being hyped. Yes, certain languages (cough Rust cough) are being hyped, but not the conscious choice of balancing programmer learning curve with runtime type-safety.

And while on the topic of Rust, it's probably not the best choice for a language that sees less runtime panics. Especially since unwrapping an error is always the easiest way to handle an error, and thus quite common. But lazy error unwrapping aside, Rust does avoid null dereference exceptions, type casting exceptions and most types of race conditions that can be quite prevalent with go[1].

[1]: https://songlh.github.io/paper/go-study.pdf

Re: Conc: Better Structured Concurrency for Go

#114

Earlier quoted context omitted.

> It was famous for good concurrency That’s because people confuse “easy” and “good”. Go has easy concurrency, but it’s not good. The opposite really. It’s at best the similar problematic model you get in other, older, procedural / oo langages. At worst it’s a lot worse given how difficult it is (and even more so was before generics) to build abstractions and concurrent data structures.

What is bad about it? An example would help me understand you better.

> What is bad about it?

That nothing about it’s good? It’s the same shared-memory concurrency everybody else has, that it had to built-in a thread-safe queue doesn’t fix that.

In some ways it makes it worse, because it’s easy for the unwary to assume channel = safe, whereas nothing could be further from the truth: a channel only protects itself, sending a slice through a channel is not safe, sending a map through a channel is not safe, sending a pointer to a channel is not safe, etc… and this is transitive, sending by value a struct which contains any of those isn’t safe either.

Not to mention the easy and common issue of implicit concurrent sharing via `go` closures.

Here’s a bunch of examples: https://www.uber.com/blog/data-race-patterns-in-go

And these are data races, not merely concurrency issues.

Re: Conc: Better Structured Concurrency for Go

#115

Earlier quoted context omitted.

What is bad about it? An example would help me understand you better.

> What is bad about it? That nothing about it’s good? It’s the same shared-memory concurrency everybody else has, that it had to built-in a thread-safe queue doesn’t fix that. In some ways it makes it worse, because it’s easy for the unwary to assume channel = safe, whereas nothing could be further from the truth: a channel only protects itself, sending a slice through a channel is not safe, sending a map through a c…

> That nothing about it’s good

You have a very myopic view of what makes concurrency designs good.

I suggest you broaden your perspective, and consider the practical effects of language design on humans, as opposed to just mathematically provable safety.

Re: Conc: Better Structured Concurrency for Go

#116

Earlier quoted context omitted.

I would agree if it weren’t super easy to cause a panic in go. Index slice out of bounds? panic. Close a channel twice? Panic. Incorrect type assertion? Panic. Dereference nil pointer? Panic. I would argue that all of these examples which are the most common in my experience are “goroutine scoped” because the goroutine was aborted before they potentially modified the application state in an unknown way. It’s like not…

> Index slice out of bounds? panic. Close a channel twice? Panic. Incorrect type assertion? Panic. Dereference nil pointer? Panic. These are all really bad things which should never survive to production code. It is not difficult to detect and prevent them. > I would argue that all of these examples which are the most common in my experience are “goroutine scoped” because the goroutine was aborted before they potenti…

> (e.g. data races) absolutely do put the program into an unknown state. Data races do not necessarily result in panics.

Many (perhaps even most?) data races would not result in panic but just in garbled, missing, duplicate, out-of-order or otherwise incorrect data.

Data-race induced panics are generally the side-effect of a data race, not a direct protection against. They can often be inconsistent: e.g. a data race in a slice that contains a binary data format could garble a variable-length string prefix and produce an index-out-of-bounds panic. Or it could prematurely consume a shared pointer and overwrite it with nil, only to have the nil pointer dereferenced by another goroutine. These kind of panics are unpredictable.

If your application has shared global state (in-memory or even a database), it may become inconsistent due to data races. But whether data-race induced indicate irreversibly corrupted global state that requires (and can be fixed with) application restart - that is case-by-case thing.

Let's say your application has some shared state that got corrupted and the corruption triggered a panic down the line.

If your shared state is persisted in a database or some other distributed mechanism and that state got corrupted: restarting the application won't help you.

If your shared state is scoped at the HTTP request level (or whichever boundary you choose for suppressing your panics): you don't need to restart the application. The request is already terminated, along with its shared state.

Which leaves us with in-memory global state. This kind of state is generally minimized in the type of microservice and network infrastructure applications that Go is often used for.

A very small percentage of your panics will indicate corruption of such state. Will you be willing to risk service downtime in order to protect against the small possibility that the service has run into a state where its shared in-memory data became corrupted?

in memory or some other distributed mechanism and that state got corrupted: restarting the application won't help you.

Re: Conc: Better Structured Concurrency for Go

#117

Earlier quoted context omitted.

I would agree if it weren’t super easy to cause a panic in go. Index slice out of bounds? panic. Close a channel twice? Panic. Incorrect type assertion? Panic. Dereference nil pointer? Panic. I would argue that all of these examples which are the most common in my experience are “goroutine scoped” because the goroutine was aborted before they potentially modified the application state in an unknown way. It’s like not…

> Index slice out of bounds? panic. Close a channel twice? Panic. Incorrect type assertion? Panic. Dereference nil pointer? Panic. These are all really bad things which should never survive to production code. It is not difficult to detect and prevent them. > I would argue that all of these examples which are the most common in my experience are “goroutine scoped” because the goroutine was aborted before they potenti…

I tend to agree with you that these are relatively easy things to detect. I see no reason for the downvotes.

Production systems should have relatively robust testing whose coverage can be increased over time. When something panics, the cause of the panic should be fixed so that the panic never happens again. Over time panics shouldn't be happening.

Then again the systems that I have relied on I have written on my own without other hands in the pot so maybe I just don't have to deal with the reality of other programmers phoning things in.

Re: Conc: Better Structured Concurrency for Go

#118

Earlier quoted context omitted.

> What is bad about it? That nothing about it’s good? It’s the same shared-memory concurrency everybody else has, that it had to built-in a thread-safe queue doesn’t fix that. In some ways it makes it worse, because it’s easy for the unwary to assume channel = safe, whereas nothing could be further from the truth: a channel only protects itself, sending a slice through a channel is not safe, sending a map through a c…

> That nothing about it’s good You have a very myopic view of what makes concurrency designs good. I suggest you broaden your perspective, and consider the practical effects of language design on humans, as opposed to just mathematically provable safety.

Ah, you’re a fanboy. You could have just put that upfront I would not have wasted my time taking you seriously.

Re: Conc: Better Structured Concurrency for Go

#119
post #53

Earlier quoted context omitted.

> In practice, panics happen. I guess this is the crux of the issue. I don't think this is true, or needs to be true. It certainly hasn't been my experience. I think assuming panics are normal will take you down some paths that make it basically impossible to write reliable software. But, to each their own. > I'm accepting the risk that my application is left in an inconsistent state, Inconsistent state makes it impo…

> assuming panics are normal will take you down some paths that make it basically impossible to write reliable software Na, citation needed. Assuming "panics are normal" is just extrapolating from "errors are normal". It makes reliable software more reliable.

it's pretty obvious that it could influence new developers into the wrong direction though. Saying things like "ha, let's not bother checking this, at worst it'll just panic and i'll simply abort the request".

Which would definitely impact the quality of the software overall in a bad way.

Re: Conc: Better Structured Concurrency for Go

#120

Earlier quoted context omitted.

> That nothing about it’s good You have a very myopic view of what makes concurrency designs good. I suggest you broaden your perspective, and consider the practical effects of language design on humans, as opposed to just mathematically provable safety.

Ah, you’re a fanboy. You could have just put that upfront I would not have wasted my time taking you seriously.

You wrote "That nothing about it’s good". That's stupid. I agree we are wasting our time.
Post reply on HN