美文网首页
go 编程的架构模式(pipe-filter)

go 编程的架构模式(pipe-filter)

作者: OOM_Killer | 来源:发表于2019-08-07 22:37 被阅读0次

    架构模式,可以使你的代码可复用性高,代码整洁,如果不用架构模式写出来的代码就是字符的堆砌,没有美感。
    掌握了golang的基础之后,就应该在之后的代码中以架构模式的方式去编程。
    第一种架构模式 pipe-filter

    pipe-filter
    • 其架构适用于 解析,过滤,处理,返回这样的架构,如数据分析。
    • filter 用于数据的过滤。而pipe 用于连接filter传递数据,或者异步处理缓冲数据流。
    • 松耦合:filter 只和数据耦合。


      pipe-filter

    下面的例子是一个将 字符串“1,2,3” 按逗号切分后,再字符转数字相加的过程。


    pipe-filter

    1、首先实现一个 filter 的接口。该接口定义了数据的来源接口,输出接口,该filter接口必须拥有的处理方法
    filter.go

    package pipe_filter
    
    // Request is the input of the filter
    type Request interface{}
    
    // Response is the output of the filter
    type Response interface{}
    
    // Filter interface is the definition of the data processing components
    // Pipe-Filter structure
    type Filter interface {
        Process(data Request) (Response, error)
    }
    

    2、定义需要的filter,在这里filter的工作顺序是串行的,首先是按“,”拆分,其次将字符型转换为数字形。最后加起来。每个filter都必须实现一个Process方法,因为只是在filter.go 里定义好的。
    split_filter.go (拆分)

    package pipe_filter
    
    import (
        "errors"
        "strings"
    )
    
    var SplitFilterWrongFormatError = errors.New("input data should be string")
    
    type SplitFilter struct {
        delimiter string
    }
    
    func NewSplitFilter(delimiter string) *SplitFilter {
        return &SplitFilter{delimiter}
    }
    
    func (sf *SplitFilter) Process(data Request) (Response, error) {
        str, ok := data.(string) //检查数据格式/类型,是否可以处理
        if !ok {
            return nil, SplitFilterWrongFormatError
        }
        parts := strings.Split(str, sf.delimiter)
        return parts, nil
    }
    

    toint_filter.go (字符转整数)

    package pipe_filter
    
    
    import (
        "errors"
        "strconv"
    )
    
    var ToIntFilterWrongFormatError = errors.New("input data should be []string")
    
    type ToIntFilter struct {
    }
    
    func NewToIntFilter() *ToIntFilter {
        return &ToIntFilter{}
    }
    
    func (tif *ToIntFilter) Process(data Request) (Response, error) {
        parts, ok := data.([]string)
        if !ok {
            return nil, ToIntFilterWrongFormatError
        }
        ret := []int{}
        for _, part := range parts {
            s, err := strconv.Atoi(part)
            if err != nil {
                return nil, err
            }
            ret = append(ret, s)
        }
        return ret, nil
    }
    

    sum_filter.go (累加)

    package pipe_filter
    
    import "errors"
    
    var SumFilterWrongFormatError = errors.New("input data should be []int")
    
    type SumFilter struct {
    }
    
    func NewSumFilter() *SumFilter {
        return &SumFilter{}
    }
    
    func (sf *SumFilter) Process(data Request) (Response, error) {
        elems, ok := data.([]int)
        if !ok {
            return nil, SumFilterWrongFormatError
        }
        ret := 0
        for _, elem := range elems {
            ret += elem
        }
        return ret, nil
    }
    

    3、定义一个pipe-line, 目的是为了将所有的filter串起来。
    pipe.go

    package pipe_filter
    
    // NewStraightPipeline create a new StraightPipelineWithWallTime
    func NewStraightPipeline(name string, filters ...Filter) *StraightPipeline {
        return &StraightPipeline{
            Name:    name,
            Filters: &filters,
        }
    }
    
    // StraightPipeline is composed of the filters, and the filters are piled as a straigt line.
    type StraightPipeline struct {
        Name    string
        Filters *[]Filter
    }
    
    // Process is to process the coming data by the pipeline
    func (f *StraightPipeline) Process(data Request) (Response, error) {
        var ret interface{}
        var err error
        for _, filter := range *f.Filters {
            ret, err = filter.Process(data)
            if err != nil {
                return ret, err
            }
            data = ret
        }
        return ret, err
    }
    
    

    这下一个完美的 pipe-filter 就完成了
    看下如何调用呢?

    package main
    
    import (
        "fmt"
        "godemo/pipe-filter"
        "log"
    )
    
    func main() {
        spliter := pipe_filter.NewSplitFilter(",")
        converter := pipe_filter.NewToIntFilter()
        sum := pipe_filter.NewSumFilter()
        sp := pipe_filter.NewStraightPipeline("p1", spliter, converter, sum)
        ret, err := sp.Process("1,2,3")
        if err != nil {
            log.Fatal(err)
        }
        if ret != 6 {
            log.Fatalf("The expected is 6, but the actual is %d", ret)
        }
        fmt.Println(ret)
    }
    
    执行结果:
    6
    

    相关文章

      网友评论

          本文标题:go 编程的架构模式(pipe-filter)

          本文链接:https://www.haomeiwen.com/subject/qoczdctx.html