// 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).typehexuint64// The compiler knows that a print of a value of this type should use// printquoted instead of printstring.typequotedstringfunc ( 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]byteprintBacklogIndexint)// 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 ( []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()}vardebuglockmutex// 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 () { := 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 () { := getg().m .printlock--if .printlock == 0 {unlock(&debuglock) }}// write to goroutine-local buffer if diverting output,// or else standard error.func ( []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 () {printstring(" ")}func () {printstring("\n")}func ( bool) {if {printstring("true") } else {printstring("false") }}// float64 requires 1+17+1+1+1+3 = 24 bytes max (sign+digits+decimal point+e+sign+exponent digits).constfloat64Bytes = 24func ( float64) {var [float64Bytes]bytegwrite(strconv.AppendFloat([:0], , 'g', -1, 64))}// float32 requires 1+9+1+1+1+2 = 15 bytes max (sign+digits+decimal point+e+sign+exponent digits).constfloat32Bytes = 15func ( float32) {var [float32Bytes]bytegwrite(strconv.AppendFloat([:0], float64(), 'g', -1, 32))}// complex128 requires 24+24+1+1+1 = 51 bytes max (paren+float64+float64+i+paren).constcomplex128Bytes = 2*float64Bytes + 3func ( complex128) {var [complex128Bytes]bytegwrite(strconv.AppendComplex([:0], , 'g', -1, 128))}// complex64 requires 15+15+1+1+1 = 33 bytes max (paren+float32+float32+i+paren).constcomplex64Bytes = 2*float32Bytes + 3func ( complex64) {var [complex64Bytes]bytegwrite(strconv.AppendComplex([:0], complex128(), 'g', -1, 64))}func ( 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 ( 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([:])}varminhexdigits = 0// protected by printlockfunc ( bool, int, uint64) {const = "0123456789abcdef"var [100]byte := len()for --; > 0; -- { [] = [%16]if < 16 && len()- >= {break } /= 16 }if { -- [] = 'x' -- [] = '0' }gwrite([:])}func ( uint64) {printhexopts(true, minhexdigits, )}func ( 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 ( unsafe.Pointer) {printhex(uint64(uintptr()))}func ( uintptr) {printhex(uint64())}func ( string) {gwrite(bytes())}func ( []byte) { := (*slice)(unsafe.Pointer(&))print("[", len(), "/", cap(), "]")printpointer(.array)}func ( eface) {print("(", ._type, ",", .data, ")")}func ( iface) {print("(", .tab, ",", .data, ")")}
The pages are generated with Goldsv0.8.4. (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.