Top 2.5% dependent repos on proxy.golang.org
proxy.golang.org : github.com/brad-jones/goasync/v2
Package goasync is a helper framework for writing asynchronous code in go. It's primary goal is to reduce the amount of boilier plate code one has to write to do concurrent tasks. TLDR: Don't care about my journey through golang's concurrency model, just want to know how this library works, skip down to The Task API. https://github.com/chebyrash/promise https://github.com/fanliao/go-promise https://github.com/capitalone/go-future-context https://github.com/rafaeldias/async http://www.golangpatterns.info/concurrency/futures https://stackoverflow.com/questions/35926173/implementing-promise-with-channels-in-go https://medium.com/strava-engineering/futures-promises-in-the-land-of-golang-1453f4807945 https://www.reddit.com/r/golang/comments/3qhgsr/futurespromises_in_the_land_of_golang Sure you can prefix any function call with `go` and it will run asynchronously but this isn't always the full story, more often than not you have to deal with the results of that function call, including any error handling strategy and at the very least some sort of method of ensuring it actually runs to completion not to mention cancelation. What is a pipeline? "Informally, a pipeline is a series of stages connected by channels, where each stage is a group of goroutines running the same function." https://blog.golang.org/pipelines If you are writting some sort of server/service (which is what go is really awesome at doing) where you might have the same async pipeline run per request. Then you can construct all of this once and it's not really a major issue. But when you need to create many different pipelines, or pipelines that have a stage that run many different functions in goroutines then a different solution is required. This is what I consider to be the basic async function: Ok so lets pull that apart: * Lets say it's idiomatic to add the `Async` suffix to any function name, much like you might prefix a function name with `Must` to denote it might panic. This follows other languages such as C#. * Any inputs to an async function must be channels, this is so that when that input is returned from another async function that channel can just be passed in and read from the goroutine, not blocking anyone else. * Similarly all returned values from an async function must be channels. Effectively we have what might be similar to a Javascript promise but broken into 2 parts, the resolver and the rejector. * Resolvers and rejectors should be buffered such that they can be executed before anything has been setup to read the channels. * A resolver or rejector will only ever send a single value to the channel. * A resolver or rejector can only be read once. A simple trick to "tee" a channel: Adding Cancelation * So we have just written 24 lines of code and only one of them actually does anything of any importance. * While there are some cases where having the resolver, rejector & stopper separate makes sense more often than not it gets hard to keep track of the pipeline with so many variables. What if fooAsync above wanted to see the error of bar, you would have to pass that in too. * Why not use context.Context? Plenty of reading about that https://dave.cheney.net/2017/08/20/context-isnt-for-cancellation Your friend is `select`, basically consider it be the replacement for the keyword `await` used in other languages. Await Any: This is how you might await for "any" of the results from a collection of async calls. Await All: This is how you might await for "all" of the results from a collection of async calls. Normally you will want to chain additional actions to take place, in the fastest way possible. Usually those functions will consume the outputs from the previous functions. So you can just pass a channel into the next function and it will wait on the channel inside it's own goroutine. My issue with this is the boilerplate code one has to write to do this. Whatever happened to DRY? I believe the methodologies outlined by this library strike a reasonable balance between writing idiomatic go and going insane repeating yourself everywhere. Whats more this is just one way things can be done, if you need something more powerful for a particular use case then the full power of go's concurrency model is still there, this library doesn't take any of that away. Up to this point all I have shown you is how to do some stuff with vanilla go and I hope that not only does it illustrate some of my frustrations with the language but also acts a useful reference to go back to when you need to do something more complex. Here is an example of `fooAsync` but this time it uses https://github.com/brad-jones/goasync/task Tasks can be awaited using https://github.com/brad-jones/goasync/await The awaiters that return early (before all tasks are complete) such as Any will cooperatively stop the remaining tasks. So cancelation will happen automatically. If you do not care for cancelation and wish to have the awaiter return as soon as possible you may uses the `Fast` awaiters. `Fast` awaiters will still ask any remaining tasks to cooperatively stop but they do so asynchronously. Or perhaps you might like to use a timeout. Due to go's lack of generics the only sane why this package can be created is by the use of the `interface{}` type. This means that all values that are returned from a task's `Result()` method or an awaiter must be casted correctly by the caller.
Registry
-
Source
- Documentation
- JSON
- codemeta.json
purl: pkg:golang/github.com/brad-jones/goasync/v2
License: MIT
Latest release: over 4 years ago
First release: about 5 years ago
Namespace: github.com/brad-jones/goasync
Dependent packages: 4
Dependent repositories: 4
Stars: 0 on GitHub
Forks: 0 on GitHub
See more repository details: repos.ecosyste.ms
Last synced: 16 days ago