• wim@lemmy.sdf.org
    link
    fedilink
    arrow-up
    12
    arrow-down
    1
    ·
    1 year ago

    Maybe it’s just me, but isn’t async programming a mess in all programming languages?

      • vrighter@discuss.tchncs.de
        link
        fedilink
        arrow-up
        6
        ·
        edit-2
        1 year ago

        not really. first of all async in not the same as threading. And even then, while it makes parallel code easier to write (not easier to reason about), it still has the exact same footguns as anything else, as soon as you venture away from having only one consumer for every producer. Synchronization is still all on you

      • wim@lemmy.sdf.org
        link
        fedilink
        arrow-up
        5
        ·
        1 year ago

        That’s a whole different thing to me. That’s not async, that’s channels and multithreading.

        I do that in Rust as well with mcsp channels and it’s been fine.

        It’s the async/await bit that I find incredibly akward all the time.

        • sugar_in_your_tea@sh.itjust.works
          link
          fedilink
          arrow-up
          3
          ·
          1 year ago

          Channels and multithreading are a solution to async problems. Instead of a keyword trying to abstract away the async, you use a mechanism for communicating between coroutines. You can run Go with a single execution thread and still get benefits from goroutines and channels. In fact, Go didn’t turn on multithreading until 1.5.

          Go solves async with goroutines and channels, not with an async keyword. The runtime is pretty heavy and steps in when standard library functions would block. In other words, it’s async by default since blocking IO causes another goroutines to execute.

          • sugar_in_your_tea@sh.itjust.works
            link
            fedilink
            arrow-up
            3
            ·
            1 year ago

            They’re very similar, but with very different ergonomics. Go channels are part of the language, so libraries use them frequently, whereas tokio is a separate library and not nearly as ubiquitous. So you’ll get stuff like this:

            c := make(chan bool)
            go func () {
                time.Sleep(time.Second*2)
                c <- true
            } ()
            
            select {
            case val := <-c:
            case _ := <-time.After(time.Second)
            }
            

            This lets you implement a simple timeout for a channel read. So the barrier to using them is really low, so they get used a ton.

            I haven’t looked at the implementation of tokio channels, so I don’t know if there’s something subtly different, but they do have the same high level functionality.