Golang笔记02之go fmt包

作者: 我加入简书的路程 | 来源:发表于2019-06-13 10:48 被阅读2次
    package main
    
    import "fmt"
    
    func main() {
        fmt.Println("Helo World")
    }
    

    上述是我刚开始学习go语言所接触的代码。和c语言一样,从“你好,世界”开始。

    首先我们看一下Println函数的源代码:

    //Println格式使用其操作数的默认格式并写入标准输出。
    //始终在操作数之间添加空格,并附加换行符。
    //它返回写入的字节(byte)数和在写入的过程中遇到的任何的错误。
    
    
    func Println(a ...interface{}) (n int, err error) {
        return Fprintln(os.Stdout, a...)
    }
    

    函数返回了一个函数Fprintln

    // These routines end in 'ln', do not take a format string,
    // always add spaces between operands, and add a newline
    // after the last operand.
    
    // Fprintln formats using the default formats for its operands and writes to w.
    // Spaces are always added between operands and a newline is appended.
    // It returns the number of bytes written and any write error encountered.
    func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
        p := newPrinter()
        p.doPrintln(a)
        n, err = w.Write(p.buf)
        p.free()
        return
    }
    

    newPrinter函数返回了一个pp结构的指针

    // newPrinter allocates a new pp struct or grabs a cached one.
    func newPrinter() *pp {
        p := ppFree.Get().(*pp)
        p.panicking = false
        p.erroring = false
        p.fmt.init(&p.buf)
        return p
    }
    
    // pp is used to store a printer's state and is reused with sync.Pool to avoid allocations.
    type pp struct {
        buf buffer
    
        // arg holds the current item, as an interface{}.
        arg interface{}
    
        // value is used instead of arg for reflect values.
        value reflect.Value
    
        // fmt is used to format basic items such as integers or strings.
        fmt fmt
    
        // reordered records whether the format string used argument reordering.
        reordered bool
        // goodArgNum records whether the most recent reordering directive was valid.
        goodArgNum bool
        // panicking is set by catchPanic to avoid infinite panic, recover, panic, ... recursion.
        panicking bool
        // erroring is set when printing an error string to guard against calling handleMethods.
        erroring bool
    }
    

    在上述的三个函数中,p其实是一个pp结构的指针。p.doprintln是一个pp结构的方法。

    // doprintln函数很像doprint,不同的是他添加了空格在不同的参数中
    // 在最后一个输出后加入换行符
    func (p *pp) doPrintln(a []interface{}) {
        for argNum, arg := range a {
            if argNum > 0 {
                p.buf.WriteByte(' ')
            }
            p.printArg(arg, 'v')
        }
        p.buf.WriteByte('\n')
    }
    
    
    n, err = w.Write(p.buf)
    

    这里的w.Write是一个什么呢?

    type Writer interface {
        Write(p []byte) (n int, err error)
    }
    

    Writer接口实现了一个Write函数,这个函数返回了我们的Fprintln需要返回了两个值。在程序的最后,我们实现了一个--》

    p.free()
    
    
    // free saves used pp structs in ppFree; avoids an allocation per invocation.
    func (p *pp) free() {
        // Proper usage of a sync.Pool requires each entry to have approximately
        // the same memory cost. To obtain this property when the stored type
        // contains a variably-sized buffer, we add a hard limit on the maximum buffer
        // to place back in the pool.
        //
        // See https://golang.org/issue/23199
        if cap(p.buf) > 64<<10 {
            return
        }
    
        p.buf = p.buf[:0]
        p.arg = nil
        p.value = reflect.Value{}
        ppFree.Put(p)
    }
    

    free函数保存了一个pp结构在ppFree中。

    end...
    由于我的技术还不够超级强,所以我的理解只能到这里,如果我后期变的更强的话,我会将这个文章的内容进行修改。

    相关文章

      网友评论

        本文标题:Golang笔记02之go fmt包

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