This commit is contained in:
kingecg 2023-12-02 13:08:31 +08:00
parent 461b545fd9
commit 4d19b8a8df
4 changed files with 225 additions and 0 deletions

7
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,7 @@
{
// 使 IntelliSense
//
// 访: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": []
}

3
go.mod Normal file
View File

@ -0,0 +1,3 @@
module git.pyer.club/kingecg/gostream
go 1.19

158
main.go Normal file
View File

@ -0,0 +1,158 @@
package gostream
import "errors"
type StreamOption struct {
WaterMark int // buffer len
}
type IReadAble[T any] interface {
StartRead() chan T
}
type IReadStream[T any] interface {
OnData(func(T)) error
Read() (T, error)
Pipe(w IWriteStream[T]) error
}
type IWriteAble[T any] interface {
StartWrite() chan T
}
type IWriteStream[T any] interface {
Write(T)
}
type WriteStream[T any] struct {
IWriteAble[T]
IWriteStream[T]
writeChan chan T
// isSync bool
}
func (w *WriteStream[T]) Write(t T) {
if w.writeChan == nil {
w.writeChan = w.StartWrite()
}
w.writeChan <- t
}
type ReadStream[T any] struct {
IReadAble[T]
IReadStream[T]
readChan chan T
isSync bool
}
// func (r *ReadStream[T]) StartRead() <-chan T {
// return nil
// }
func (r *ReadStream[T]) OnData(cb func(T)) error {
if r.readChan != nil {
return errors.New("already has reader")
}
r.readChan = r.StartRead()
go func() {
for t := range r.readChan {
cb(t)
}
}()
return nil
}
func (r *ReadStream[T]) Read() (T, error) {
if r.readChan != nil && !r.isSync {
return *new(T), errors.New("already has reader")
}
if r.readChan == nil {
r.readChan = r.StartRead()
r.isSync = true
}
return <-r.readChan, nil
}
func (r *ReadStream[T]) Pipe(w IWriteStream[T]) error {
if r.readChan != nil {
return errors.New("already has reader")
}
r.readChan = r.StartRead()
go func() {
for t := range r.readChan {
w.Write(t)
}
}()
return nil
}
type ITransformer[T any, K any] interface {
Transform(t T) K
}
type TransformStream[T any, K any] struct {
Options StreamOption
IWriteAble[T]
WriteStream[T]
IReadAble[K]
ReadStream[K]
ITransformer[T, K]
writer chan T
reader chan K
}
func (tr *TransformStream[T, K]) StartRead() chan K {
if tr.reader != nil {
return tr.reader
}
return make(chan K, tr.Options.WaterMark)
}
func (tr *TransformStream[T, K]) StartWrite() chan T {
if tr.writer != nil {
return tr.writer
}
return make(chan T, tr.Options.WaterMark)
}
func (tr *TransformStream[T, K]) OnData(cb func(K)) error {
err := tr.ReadStream.OnData(cb)
if err == nil {
if tr.writer == nil {
tr.writer = tr.StartWrite()
}
go func() {
for k := range tr.writer {
transfered := tr.ITransformer.Transform(k)
tr.reader <- transfered
}
}()
}
return err
}
func NewTransform[T any, K any](t ITransformer[T, K], options StreamOption) *TransformStream[T, K] {
ret := &TransformStream[T, K]{
Options: options,
ITransformer: t,
ReadStream: ReadStream[K]{},
WriteStream: WriteStream[T]{},
}
ret.ReadStream.IReadAble = ret
ret.WriteStream.IWriteAble = ret
return ret
}
func NewReadStream[T any](reader IReadAble[T]) *ReadStream[T] {
ret := &ReadStream[T]{
IReadAble: reader,
}
return ret
}
func NewWriteStream[T any](writer IWriteAble[T]) *WriteStream[T] {
ret := &WriteStream[T]{
IWriteAble: writer,
}
return ret
}

57
test/main.go Normal file
View File

@ -0,0 +1,57 @@
package main
import (
"fmt"
"git.pyer.club/kingecg/gostream"
)
type TReadAble[T any] struct {
gostream.ReadStream[T]
sended int
E []T
}
func (tr *TReadAble[T]) StartRead() chan T {
// var d T
// if tr.sended < len(tr.E) {
// d = tr.E[tr.sended]
// tr.sended++
// return &d
// }
// return nil
ch := make(chan T)
go func() {
for i := 0; i < len(tr.E); i++ {
ch <- tr.E[i]
}
close(ch)
}()
return ch
}
func main() {
x := &TReadAble[int]{
gostream.ReadStream[int]{},
0,
[]int{1, 2, 3, 4, 5},
}
x.ReadStream.IReadAble = x
// x.OnData(func(d int) {
// fmt.Println(d)
// })
fmt.Println(x.Read())
fmt.Println(x.Read())
fmt.Println(x.Read())
fmt.Println(x.Read())
// for t := tr.DoRead(); t != nil; t = tr.DoRead() {
// fmt.Println(*t)
// }
// tr.OnData(func(d int) {
// fmt.Println("tr.OnData", d)
// })
select {}
}