Golang笔记02之go fmt包

我加入简书的路程 · · 104 次点击 · · 开始浏览    
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包

入群交流(和以上内容无关):Go中文网 QQ 交流群:798786647 或加微信入微信群:274768166 备注:入群;关注公众号:Go语言中文网

104 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传