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...
由于我的技术还不够超级强,所以我的理解只能到这里,如果我后期变的更强的话,我会将这个文章的内容进行修改。
有疑问加站长微信联系(非本文作者)