zoukankan      html  css  js  c++  java
  • 如何减少重复err

    曾看到一篇blog,说他们一个项目最后扫盲出几千个

    if err != nil

    没有对比就没有伤害

    Golang的主程都是工程界的高手,而且还有一堆geek社区,自然有办法让err,不那么难看。几个示例

    参考Rob Pike的一篇blog

    https://blog.golang.org/errors-are-values

    io.Writer 例子:

    _, err = fd.Write(p0[a:b])
    if err != nil {
        return err
    }
    _, err = fd.Write(p1[c:d])
    if err != nil {
        return err
    }
    _, err = fd.Write(p2[e:f])
    if err != nil {
        return err
    }
    // and so on

    这看起来太糟糕了,虽然实际可能不会重复的Write。改进之

    var err error
    write := func(buf []byte) {
        if err != nil {
            return
        }
        _, err = w.Write(buf)
    }
    write(p0[a:b])
    write(p1[c:d])
    write(p2[e:f])
    // and so on
    if err != nil {
        return err
    }

    闭包的方式,这里的缺点是需要维护一个err,如果我们想用一些其他的辅助函数,反而甚至会更麻烦。

    直接定义一个对象吧

    type errWriter struct {
        w   io.Writer
        err error
    }
    func (ew *errWriter) write(buf []byte) {
        if ew.err != nil {
            return
        }
        _, ew.err = ew.w.Write(buf)
    }
    ew := &errWriter{w: fd}
    ew.write(p0[a:b])
    ew.write(p1[c:d])
    ew.write(p2[e:f])
    // and so on
    if ew.err != nil {
        return ew.err
    }

    例子二

    参考Dave Cheney的一篇blog

    https://dave.cheney.net/2019/01/27/eliminate-error-handling-by-eliminating-errors

    type Header struct {
        Key, Value string
    }
    
    type Status struct {
        Code   int
        Reason string
    }
    
    func WriteResponse(w io.Writer, st Status, headers []Header, body io.Reader) error {
        _, err := fmt.Fprintf(w, "HTTP/1.1 %d %s
    ", st.Code, st.Reason)
        if err != nil {
            return err
        }
    
        for _, h := range headers {
            _, err := fmt.Fprintf(w, "%s: %s
    ", h.Key, h.Value)
            if err != nil {
                return err
            }
        }
    
        if _, err := fmt.Fprint(w, "
    "); err != nil {
            return err
        }
    
        _, err = io.Copy(w, body)
        return err
    }

    这里的问题是下面这个函数都会返回一个err,本质上还是io.Writer的问题

    func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
    ...
    }

    改进

    type errWriter struct {
        io.Writer
        err error
    }
    
    func (e *errWriter) Write(buf []byte) (int, error) {
        if e.err != nil {
            return 0, e.err
        }
    
        var n int
        n, e.err = e.Writer.Write(buf)
        return n, nil
    }
    
    type Header struct {
        Key, Value string
    }
    
    type Status struct {
        Code   int
        Reason string
    }
    
    func WriteResponse(w io.Writer, st Status, headers []Header, body io.Reader) error {
        ew := &errWriter{Writer:w}
    
        fmt.Fprintf(ew, "HTTP/1.1 %d %s
    ", st.Code, st.Reason)
    
    
        for _, h := range headers {
            fmt.Fprintf(ew, "%s: %s
    ", h.Key, h.Value)
        }
    
        fmt.Fprint(w, "
    ")
    
        io.Copy(ew, body)
        return ew.err
    }

    第三个例子

    func CountLines(r io.Reader) (int, error) {
        var (
            br    = bufio.NewReader(r)
            lines int
            err   error
        )
    
        for {
            _, err = br.ReadString('
    ')
            lines++
            if err != nil {
                break
            }
        }
    
        if err != io.EOF {
            return 0, err
        }
    
        return lines, nil
    }

    改进

    func CountLines(r io.Reader) (int, error) {
        sc := bufio.NewScanner(r)
        lines := 0
    
        for sc.Scan() {
            lines++
        }
    
        return lines, sc.Err()
    }
    type Scanner struct {
        r            io.Reader // The reader provided by the client.
        split        SplitFunc // The function to split the tokens.
        maxTokenSize int       // Maximum size of a token; modified by tests.
        token        []byte    // Last token returned by split.
        buf          []byte    // Buffer used as argument to split.
        start        int       // First non-processed byte in buf.
        end          int       // End of data in buf.
        err          error     // Sticky error.
        empties      int       // Count of successive empty tokens.
        scanCalled   bool      // Scan has been called; buffer is in use.
        done         bool      // Scan has finished.
    }

    可以看到Scanner是高一级的封装对象,Scan() 内部就处理了err

    参考

    https://blog.huoding.com/2019/04/11/728

    end

    一个没有高级趣味的人。 email:hushui502@gmail.com
  • 相关阅读:
    QT5:类总结
    QT5:控件
    QT5:事件
    杂谈感想:致毛星云大佬
    QT5:3D
    QT5:其他问题
    QT5:文件
    iOS开发小技巧
    vs2010 学习Silverlight学习笔记(24):TransForm处理图片
    vs2010 学习Silverlight学习笔记(25):综合图片应用和《功夫之王》相册
  • 原文地址:https://www.cnblogs.com/CherryTab/p/12831242.html
Copyright © 2011-2022 走看看