// Copyright 2009 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package runtimeimport ()// The compiler knows that a print of a value of this type// should use printhex instead of printuint (decimal).type hex uint64// The compiler knows that a print of a value of this type should use// printquoted instead of printstring.type quoted stringfunc bytes( string) ( []byte) { := (*slice)(unsafe.Pointer(&)) := stringStructOf(&) .array = .str .len = .len .cap = .lenreturn}var (// printBacklog is a circular buffer of messages written with the builtin // print* functions, for use in postmortem analysis of core dumps. printBacklog [512]byte printBacklogIndex int)// recordForPanic maintains a circular buffer of messages written by the// runtime leading up to a process crash, allowing the messages to be// extracted from a core dump.//// The text written during a process crash (following "panic" or "fatal// error") is not saved, since the goroutine stacks will generally be readable// from the runtime data structures in the core file.func recordForPanic( []byte) {printlock()ifpanicking.Load() == 0 {// Not actively crashing: maintain circular buffer of print output.for := 0; < len(); { := copy(printBacklog[printBacklogIndex:], [:]) += printBacklogIndex += printBacklogIndex %= len(printBacklog) } }printunlock()}var debuglock mutex// The compiler emits calls to printlock and printunlock around// the multiple calls that implement a single Go print or println// statement. Some of the print helpers (printslice, for example)// call print recursively. There is also the problem of a crash// happening during the print routines and needing to acquire// the print lock to print information about the crash.// For both these reasons, let a thread acquire the printlock 'recursively'.func printlock() { := getg().m .locks++ // do not reschedule between printlock++ and lock(&debuglock). .printlock++if .printlock == 1 {lock(&debuglock) } .locks-- // now we know debuglock is held and holding up mp.locks for us.}func printunlock() { := getg().m .printlock--if .printlock == 0 {unlock(&debuglock) }}// write to goroutine-local buffer if diverting output,// or else standard error.func gwrite( []byte) {iflen() == 0 {return }recordForPanic() := getg()// Don't use the writebuf if gp.m is dying. We want anything // written through gwrite to appear in the terminal rather // than be written to in some buffer, if we're in a panicking state. // Note that we can't just clear writebuf in the gp.m.dying case // because a panic isn't allowed to have any write barriers.if == nil || .writebuf == nil || .m.dying > 0 {writeErr()return } := copy(.writebuf[len(.writebuf):cap(.writebuf)], ) .writebuf = .writebuf[:len(.writebuf)+]}func printsp() {printstring(" ")}func printnl() {printstring("\n")}func printbool( bool) {if {printstring("true") } else {printstring("false") }}func printfloat64( float64) {var [20]bytegwrite(strconv.AppendFloat([:0], , 'g', -1, 64))}func printfloat32( float32) {var [20]bytegwrite(strconv.AppendFloat([:0], float64(), 'g', -1, 32))}func printcomplex128( complex128) {var [44]bytegwrite(strconv.AppendComplex([:0], , 'g', -1, 128))}func printcomplex64( complex64) {var [44]bytegwrite(strconv.AppendComplex([:0], complex128(), 'g', -1, 64))}func printuint( uint64) {// Note: Avoiding strconv.AppendUint so that it's clearer // that there are no allocations in this routine. // cmd/link/internal/ld.TestAbstractOriginSanity // sees the append and doesn't realize it doesn't allocate.var [20]byte := strconv.RuntimeFormatBase10([:], )gwrite([:])}func printint( int64) {// Note: Avoiding strconv.AppendUint so that it's clearer // that there are no allocations in this routine. // cmd/link/internal/ld.TestAbstractOriginSanity // sees the append and doesn't realize it doesn't allocate. := < 0 := uint64()if { = - }var [20]byte := strconv.RuntimeFormatBase10([:], )if { -- [] = '-' }gwrite([:])}var minhexdigits = 0// protected by printlockfunc printhexopts( bool, int, uint64) {const = "0123456789abcdef"var [100]byte := len()for --; > 0; -- { [] = [%16]if < 16 && len()- >= {break } /= 16 }if { -- [] = 'x' -- [] = '0' }gwrite([:])}func printhex( uint64) {printhexopts(true, minhexdigits, )}func printquoted( string) {printlock()gwrite([]byte(`"`))for , := range {switch {case'\n':gwrite([]byte(`\n`))continuecase'\r':gwrite([]byte(`\r`))continuecase'\t':gwrite([]byte(`\t`))print()continuecase'\\', '"':gwrite([]byte{byte('\\'), byte()})continue }// For now, only allow basic printable ascii through unescapedif >= ' ' && <= '~' {gwrite([]byte{byte()}) } elseif < 127 {gwrite(bytes(`\x`))printhexopts(false, 2, uint64()) } elseif < 0x1_0000 {gwrite(bytes(`\u`))printhexopts(false, 4, uint64()) } else {gwrite(bytes(`\U`))printhexopts(false, 8, uint64()) } }gwrite([]byte{byte('"')})printunlock()}func printpointer( unsafe.Pointer) {printhex(uint64(uintptr()))}func printuintptr( uintptr) {printhex(uint64())}func printstring( string) {gwrite(bytes())}func printslice( []byte) { := (*slice)(unsafe.Pointer(&))print("[", len(), "/", cap(), "]")printpointer(.array)}func printeface( eface) {print("(", ._type, ",", .data, ")")}func printiface( iface) {print("(", .tab, ",", .data, ")")}
The pages are generated with Goldsv0.8.3-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.