Live data from Hacker News

Coroutines for Go

research.swtch.com

111–120 of 191 posts

Re: Coroutines for Go

#111
post #74

Earlier quoted context omitted.

This has been under discussion for a long time. https://github.com/golang/go/issues/43557 https://github.com/golang/go/discussions/56413 I'm not sure Russ's personal blog is any kind of official statement "this is what we're doing" yet?

> I'm not sure Russ's personal blog is any kind of official statement "this is what we're doing" yet? I've found it's generally a very strong indicator. But to your point, this isn't a new issue, there's been a good amount of discussion around it over the years.

In the old discussion, I specifically complained about how it would add back door coroutines to Go via iterators, and now Russ has a post about formalizing the concept of a coroutine, while also keeping the optimization of coroutines as a runtime implementation detail. I feel vindicated. :-)

https://github.com/golang/go/discussions/56413#discussioncom...

Re: Coroutines for Go

#112

Multitasking systems gave us processes. But those were too much. So we got threads, which are processes that share an address space, file table, and some other things. The scheduler can switch from one to the other more easily than between processes, and data can be shared between threads without needing serialization. But those were too much. So we got user space threads, which are logical threads of execution that…

I don’t think there’s any further down to go, but there’s probably room to go up to distributed computing. IIRC, some early versions of Go when it was in alpha had channels work across machines.

Re: Coroutines for Go

#113
post #78

Earlier quoted context omitted.

You’re absolutely right. People advocating for it can’t seem to see beyond their nose.

More likely they're trying to solve real problems you just haven't hit yet.

The go team has explicitly said this is the past: “You just don’t understand because you’re not at Google’s scale.”

Re: Coroutines for Go

#114

Reading the comments makes me feel bittersweet. - Many people consider coroutines and green threads to be more or less the same thing, when they both have their pros and cons. - The fact that the omission of iterators is even acceptable in the Go community saddens me. They seem to deliberately refuse any feature that might make the language even slightly more complex, in the name of simplicity. But hey, at least they…

I wouldn’t confuse HN with “the Go community”. The head of the Go team wrote this post. Will the coro package proposed in the post be added exactly as written? Maybe, but probably not exactly as written. Will something like it be added? I would be willing to bet money on it, yes. How long will it take? I’d say at least a year (release in Go 1.23 in August of 2024), maybe a little longer. I don’t think it could be much shorter though.

Re: Coroutines for Go

#115

I have written Go professionally for many years now and don't want to see it become something like the Python Twisted / Tornado / whatever frameworks. The go keyword nicely prevents the annoying function coloring problem, which causes quite a bit of pain. Sometimes in high performance contexts I'd like to be able to do something like e.g. per CPU core data sharding, but this proposal doesn't scratch those kinds of it…

Can you maybe share hints to better channel management patterns/frameworks? Usually my goroutines related code feels like a mess because of them, and I don't know how to make them "more clean" (whatever that means). Any hints proven to be maintainable patterns would be highly appreciated.

I don't always use channels in the code I write.

For example, let's say I have []foo as input and I'm going to call a service on every element of the slice.

You could do it with channels, but oftentimes I'll reach for creating a slice of results and passing each goroutine an index into the slice. That way I can avoid any overhead that comes from having what is effectively a queue with a lock.

It depends on what I'm doing, how I want to treat failures of a single goroutine, etc. of course.

I default to never returning channels unless it's a requirement for the use case (e.g. context.Done() returns a channel so callers can listen for when the context is closed).

Callers can always create goroutines to make your code run concurrently. It's more annoying to erase channels when they aren't useful to the caller (e.g. if you made all functions that make HTTP calls return a channel because you assume callers want a new goroutine, but I already have my own goroutine per request)

Beyond that, some specific examples would be helpful so I can tailor my advice

Re: Coroutines for Go

#116
post #91

Earlier quoted context omitted.

Goroutines and channels aren't intuitive either. You learn them and become familiar with them over time, at which point they become intuitive __for you__.

They're totally intuitive if you were an Occam programmer.

So it's intuitive because you are familiar with those concepts. I don't see how that goes against what I said.

Re: Coroutines for Go

#117
post #2

Not sure I'm a fan. Looking through the examples, I feel like this makes the language much harder to read and follow, but maybe that's just my own brain and biases. Further, it doesn't seem to me to allow you to do anything you can't currently do with blocking channels and/or state.

What language change are you talking about? This is just a proposed construct to regularise and make efficient something people already do (as you says with “state”).

I’ve used iterators similar to what’s described in this article to avoid allocations in critical code paths, but this would make those much less awkward to use (particularly with the upcoming range iterator language change).

Re: Coroutines for Go

#118

Earlier quoted context omitted.

Looking at python's asyncio coroutine library, they are just mocking multithreading with asyncio.gather. Since coroutines can be executed in any order they are not really control-flow mechanisms. The selling point of coroutines over traditional threads is its lightweight but its moot since goroutines has similar memory cost to coroutines. The only real benefit is that coroutines are non blocking while goroutines may…

The concept of "coroutines" is as much about control flow as "subroutines" (function calls and return statements). But when you have a construct that has their own call stacks, it's a relatively small step to implement lightweight threads with it. Since doing concurrency happens much more often than any other smart use of coroutines, many people conflate the two. I sometimes see this confusion in discussions about Ko…

Kotlin's sequence pre-dates co-routines. Mostly what either of those do is just a bit of syntactic sugar on top of call back mechanisms. One of the nice things with Kotlin is the ability to extend existing APIs via extension functions. Which is something the co-routines library uses extensively to be able to provide co-routine implementations on top of existing frameworks on the JVM, in javascript, and in native environments. Same APIs. Same code. Different underlying implementations. I actively use this in some of my multi platform libraries that I use on JVM and in the browser.

The key concept with Kotlin's co-routines is not having to choose between reactive, green threads, or real threads but treating all of those in the same way with a robust set of abstractions. I use co-routines in the browser on top of existing javascript frameworks that return promises. I use them on the JVM with reactive frameworks like flux. And I also use them with some thread pools. Once Loom reaches LTS (next year, I think), I'll probably be configuring some Loom capable co-routine dispatchers as well.

The debate regarding co-routines vs. go-routines seems like it is similar. I think Go can learn a thing or two from Kotlin's co-routines. After all it is mostly built as a library on top of a single language feature: the suspend keyword. I get that not everybody likes colored functions. But then having a lot of leaky abstractions and related complexity on top of go routines is maybe also not ideal.

Re: Coroutines for Go

#119

Earlier quoted context omitted.

The concept of "coroutines" is as much about control flow as "subroutines" (function calls and return statements). But when you have a construct that has their own call stacks, it's a relatively small step to implement lightweight threads with it. Since doing concurrency happens much more often than any other smart use of coroutines, many people conflate the two. I sometimes see this confusion in discussions about Ko…

Kotlin's sequence pre-dates co-routines. Mostly what either of those do is just a bit of syntactic sugar on top of call back mechanisms. One of the nice things with Kotlin is the ability to extend existing APIs via extension functions. Which is something the co-routines library uses extensively to be able to provide co-routine implementations on top of existing frameworks on the JVM, in javascript, and in native envi…

> Kotlin's sequence pre-dates co-routines.

You misunderstood. The `Sequence` type does predate coroutines. But I meant the `sequence` builder function, which takes a block of suspending code to create a `Sequence`.

The in-order traversal in the article can be translated to Kotlin:

    fun walk(t: Tree?): Sequence = sequence {
        if (t != null) {
            yieldAll(walk(t.left))
            yield(t.value)
            yieldAll(walk(t.right))
        }
    }
As I have noted above, this is a use of coroutines that has nothing to do with concurrency.

Re: Coroutines for Go

#120
post #105

Earlier quoted context omitted.

Only newbies tend to complain about `err != nil` in my experience. After a certain point it just clicks and they get used to it. There's a cadence to Go code (do the thing, check the error, do the thing, check the error) that is easy to read once you're used to it, but looks horribly verbose when you're coming from an exceptions-based language. Go has simplicity as a design goal. Part of that simplicity is not adding…

>This seems like a "can implement, but not very cleanly" case, which would be a great justification for a library, but not a language feature. First sentence of OP: > This post is about why we need a coroutine package for Go Then in the girst section after the intro: > Later, I will argue for an optimized implementation provided directly by the runtime, but that implementation should be indistinguishable from the pur…

Yeah, so I'm agreeing that this would be a great library, but disagreeing that it should be a language feature. Sorry if I didn't make that clear.
Post reply on HN