美文网首页golang
Go 实现责任链模式

Go 实现责任链模式

作者: 三梦哥 | 来源:发表于2021-12-19 19:14 被阅读0次
    package main
    
    import (
        "context"
        "errors"
        "fmt"
        "log"
        "net/http"
    )
    
    type Request struct {
        Data   string
        Name   string
        Upload string
    }
    
    type Response struct {
    }
    
    type Context struct {
        Req      *Request
        Resp     *Response
        handlers []FilterFunc
        index    int
    }
    
    func (c *Context) Next() error {
        c.index++
        s := len(c.handlers)
        for ; c.index <= s; c.index++ {
            if err := c.handlers[c.index-1](c); err != nil {
                return err
            }
        }
        return nil
    }
    
    type Filter interface {
        Handle(ctx *Context) error
    }
    
    type FilterFunc func(ctx *Context) error
    
    type FilterDecorator struct {
        filters []FilterFunc
    }
    
    func NewFilterDecorator() *FilterDecorator {
        return &FilterDecorator{}
    }
    
    func (d *FilterDecorator) Use(middlewares ...FilterFunc) {
        d.filters = append(d.filters, middlewares...)
    }
    
    func (d *FilterDecorator) Do(request *Request, response *Response) error {
        c := new(Context)
        c.Req = request
        c.Resp = response
        c.handlers = d.filters
        return c.Next()
    }
    
    func ValidateParam() FilterFunc {
        return func(ctx *Context) error {
            req := ctx.Req
            if req.Name != "Tom" {
                return errors.New("name is not Tom")
            }
            ctx.Next()
            return nil
        }
    }
    
    func ProcessFilter() FilterFunc {
        return func(ctx *Context) (err error) {
            log.Println("processing ProcessFilter")
            defer func() {
                log.Println("after ProcessFilter")
            }()
            ctx.Req.Name = "Jack"
            if err := ctx.Next(); err != nil {
                return err
            }
            return nil
        }
    }
    
    type Uploader interface {
        Upload(ctx context.Context, data string) error
    }
    
    type UploaderFunc func(ctx context.Context, data string) error
    
    func (u UploaderFunc) Upload(ctx context.Context, data string) error {
        return u(ctx, data)
    }
    
    type AliyunClient struct {
        c *http.Client
    }
    
    func NewAliyunClient() *AliyunClient {
        return &AliyunClient{}
    }
    
    func (a *AliyunClient) Upload(ctx context.Context, data string) error {
        log.Printf("AliyunClient Upload:%s", data)
        return nil
    }
    
    type AwsClient struct {
        c *http.Client
    }
    
    func NewAwsClient() *AwsClient {
        return &AwsClient{}
    }
    
    func (a *AwsClient) Upload(ctx context.Context, data string) error {
        log.Printf("AwsClient Upload:%s", data)
        return nil
    }
    
    func AzureUpload() UploaderFunc {
        return func(ctx context.Context, data string) error {
            log.Printf("AzureClient Upload:%s", data)
            return nil
        }
    
    }
    
    func UploadFilter() FilterFunc {
        aliyun := NewAliyunClient()
        aws := NewAwsClient()
        uploaderMap := map[string]Uploader{
            "aliyun": aliyun,
            "aws":    aws,
            "azure":  AzureUpload(),
        }
        log.Println("--Hello World")
        return func(ctx *Context) (err error) {
            log.Println("processing UploadFilter")
            fmt.Printf("Name:%s\n", ctx.Req.Name)
            var uploader Uploader
            uploader, ok := uploaderMap[ctx.Req.Upload]
            if !ok {
                uploader = aliyun
            }
            if err = uploader.Upload(context.Background(), ctx.Req.Data); err != nil {
                return
            }
            if err := ctx.Next(); err != nil {
                return err
            }
            return nil
        }
    }
    
    func main() {
        d := NewFilterDecorator()
        d.Use(ValidateParam())
        d.Use(ProcessFilter())
        d.Use(UploadFilter())
        req := new(Request)
        req.Data = "Hello World"
        req.Upload = "azure"
        resp := new(Response)
        if err := d.Do(req, resp); err != nil {
            log.Println(err)
        }
    }
    
    

    相关文章

      网友评论

        本文标题:Go 实现责任链模式

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