// 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 uint64func 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 printfloat( float64) {switch {case != :printstring("NaN")returncase + == && > 0:printstring("+Inf")returncase + == && < 0:printstring("-Inf")return }const = 7// digits printedvar [ + 7]byte [0] = '+' := 0// expif == 0 {if1/ < 0 { [0] = '-' } } else {if < 0 { = - [0] = '-' }// normalizefor >= 10 { ++ /= 10 }for < 1 { -- *= 10 }// round := 5.0for := 0; < ; ++ { /= 10 } += if >= 10 { ++ /= 10 } }// format +d.dddd+eddfor := 0; < ; ++ { := int() [+2] = byte( + '0') -= float64() *= 10 } [1] = [2] [2] = '.' [+2] = 'e' [+3] = '+'if < 0 { = - [+3] = '-' } [+4] = byte(/100) + '0' [+5] = byte(/10)%10 + '0' [+6] = byte(%10) + '0'gwrite([:])}func printcomplex( complex128) {print("(", real(), imag(), "i)")}func printuint( uint64) {var [100]byte := len()for --; > 0; -- { [] = byte(%10 + '0')if < 10 {break } /= 10 }gwrite([:])}func printint( int64) {if < 0 {printstring("-") = - }printuint(uint64())}var minhexdigits = 0// protected by printlockfunc printhex( uint64) {const = "0123456789abcdef"var [100]byte := len()for --; > 0; -- { [] = [%16]if < 16 && len()- >= minhexdigits {break } /= 16 } -- [] = 'x' -- [] = '0'gwrite([:])}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, ")")}// hexdumpWords prints a word-oriented hex dump of [p, end).//// If mark != nil, it will be called with each printed word's address// and should return a character mark to appear just before that// word's value. It can return 0 to indicate no mark.func hexdumpWords(, uintptr, func(uintptr) byte) {printlock()var [1]byte [0] = ' 'minhexdigits = int(unsafe.Sizeof(uintptr(0)) * 2)for := uintptr(0); + < ; += goarch.PtrSize {if %16 == 0 {if != 0 {println() }print(hex(+), ": ") }if != nil { [0] = ( + )if [0] == 0 { [0] = ' ' } }gwrite([:]) := *(*uintptr)(unsafe.Pointer( + ))print(hex())print(" ")// Can we symbolize val? := findfunc()if .valid() {print("<", funcname(), "+", hex(-.entry()), "> ") } }minhexdigits = 0println()printunlock()}
The pages are generated with Goldsv0.7.0-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.