https://github.com/ksloveyuan/channelx
Some useful tools implemented by channel to increase development efficiency, e.g. event bus, promise, actor, stream, aggregator, goroutine pool, etc..
https://github.com/ksloveyuan/channelx
actor concurrency eventbus golang promise stream
Last synced: 5 months ago
JSON representation
Some useful tools implemented by channel to increase development efficiency, e.g. event bus, promise, actor, stream, aggregator, goroutine pool, etc..
- Host: GitHub
- URL: https://github.com/ksloveyuan/channelx
- Owner: Ksloveyuan
- License: mit
- Created: 2019-09-07T16:00:39.000Z (almost 7 years ago)
- Default Branch: master
- Last Pushed: 2021-09-21T14:17:12.000Z (almost 5 years ago)
- Last Synced: 2024-06-20T12:06:04.694Z (about 2 years ago)
- Topics: actor, concurrency, eventbus, golang, promise, stream
- Language: Go
- Homepage:
- Size: 66.4 KB
- Stars: 87
- Watchers: 5
- Forks: 18
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# channelx
[](https://goreportcard.com/report/github.com/Ksloveyuan/channelx)
[](https://api.travis-ci.org/Ksloveyuan/channelx.svg?branch=master)
[](https://codecov.io/gh/Ksloveyuan/channelx)
[](https://godoc.org/github.com/Ksloveyuan/channelx)
Some useful tools implemented by channel to increase development efficiency, e.g. event bus, stream, promise, actor, parallel runner, aggregator, etc..
# blogs
- [如何把Golang的channel用的如nodejs的stream一样丝滑](https://juejin.im/post/5d7ba76ef265da03be490856)
- [如何用Golang的channel实现消息的批量处理](https://juejin.im/post/5d8c6775e51d45781332e91f)
- [如何把Golang的Channel玩出async和await的feel](https://juejin.im/post/5e4175a36fb9a07ca80a9c77)
- [下次想在Golang中写个并发处理,就用这个模板,准没错!](https://juejin.cn/post/6959369791937347621/)
- [玩转Golang的channel,二百行代码实现PubSub模式](https://juejin.cn/post/7010383321674809352)
## Parallel runner
A simple util to run tasks in parallel
```golang
worker := func(ctx context.Context, input interface{}) (interface{}, error) {
num := input.(int)
return num+1, nil
}
inputs := []interface{}{1,2,3,4,5}
outputs, err := channelx.RunInParallel(context.Background(), inputs, worker, 4)
```
more examples, please check [parallel_runner_test.go](https://github.com/Ksloveyuan/channelx/blob/master/parallel_runner_test.go)
### EventBus
A PubSub pattern util
```golang
logger := channelx.NewConsoleLogger()
eventBus := channelx.NewEventBus(logger, 4,4,2, time.Second, 5 * time.Second)
eventBus.Start()
handler := NewExampleHandler(logger)
eventBus.Subscribe(ExampleEventID, handler)
eventBus.Publish(NewExampleEvent())
eventBus.Stop()
```
more details, please check [event_bus_test.go#TestEventBus_Example](https://github.com/Ksloveyuan/channelx/blob/master/event_bus_test.go#L103)
## Promise
A golang style async/await, even I call it Promise, while the api is not 100% aligns with Javascript Promise.
```golang
promise := NewPromise(func() (res interface{}, err error) {
// do work asynchronously here
reuturn
}).Then(func(input interface{}) (interface{}, error) {
// here is the succss handler, which aslo runs asynchronously
}, func(err error) interface{} {
// here is the error handler, which aslo runs asynchronously
})
// await: wait until it completes.
res, _ := promise.Done()
```
more examples, please check [promise_test.go](https://github.com/Ksloveyuan/channelx/blob/master/promise_test.go)
## Actor
The actor pattern is also called as Active Object, it seems like Promise, but the difference is Actor can be reused, and it is FIFO.
```golang
actor := NewActor(SetActorBuffer(0))
defer actor.Close()
// do some work asynchroniously.
call := actor.Do(func() (interface{}, error) {
time.Sleep(0 * time.Second)
return 0, nil
})
// can to some other synchroniouse work here
// ......
// wait for the call completes.
res, err := call.Done()
```
more examples, please check [actor_test.go](https://github.com/Ksloveyuan/channelx/blob/master/actor_test.go)
## Stream
Steam works like Node.Js stream, it can be piped and data flows through the pipe one by one.
### before
```golang
var multipleChan = make(chan int, 4)
var minusChan = make(chan int, 4)
var harvestChan = make(chan int, 4)
defer close(multipleChan)
defer close(minusChan)
defer close(harvestChan)
go func() {
for i:=1;i<=100;i++{
multipleChan <- i
}
}()
for i:=0; i<4; i++{
go func() {
for data := range multipleChan {
minusChan <- data * 2
time.Sleep(10* time.Millisecond)
}
}()
go func() {
for data := range minusChan {
harvestChan <- data - 1
time.Sleep(10* time.Millisecond)
}
}()
}
var sum = 0
var index = 0
for data := range harvestChan{
sum += data
index++
if index == 100{
break
}
}
fmt.Println(sum)
```
### after
```golang
var sum = 0
NewChannelStream(func(seedChan chan<- Item, quitChannel chan struct{}) {
for i:=1; i<=100;i++{
seedChan <- Item{Data:i}
}
close(seedChan) //don't forget to close it
}).Pipe(func(Item Item) Item {
return Item{Data: Item.Data.(int) * 2}
}).Pipe(func(Item Item) Item {
return Item{Data: Item.Data.(int) - 1}
}).Harvest(func(Item Item) {
sum += Item.Data.(int)
})
fmt.Println(sum)
```
more examples, please check [stream_test.go](https://github.com/Ksloveyuan/channelx/blob/master/stream_test.go)
## Aggregator
Aggregator is used for the scenario that receives request one by one while handle them in a batch would increase efficiency.
```golang
// YourKnownType, YourBatchHandler, yourRequest are faked type or object
batchProcess := func(items []interface{}) error {
var arr YourKnownType
for _, item := range items{
ykt := item.(YourKnownType)
arr = append(arr, ykt)
}
YourBatchHandler(arr)
}
aggregator := NewAggregator(batchProcess)
aggregator.Start()
aggregator.Enqueue(yourRequest)
aggregator.Stop()
```
more examples, please check [aggregator_test.go](https://github.com/Ksloveyuan/channelx/blob/master/aggregator_test.go)