Source File
log.go
Belonging Package
log
// 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 log implements a simple logging package. It defines a type, [Logger],// with methods for formatting output. It also has a predefined 'standard'// Logger accessible through helper functions Print[f|ln], Fatal[f|ln], and// Panic[f|ln], which are easier to use than creating a Logger manually.// That logger writes to standard error and prints the date and time// of each logged message.// Every log message is output on a separate line: if the message being// printed does not end in a newline, the logger will add one.// The Fatal functions call [os.Exit](1) after writing the log message.// The Panic functions call panic after writing the log message.package logimport ()// These flags define which text to prefix to each log entry generated by the [Logger].// Bits are or'ed together to control what's printed.// With the exception of the Lmsgprefix flag, there is no// control over the order they appear (the order listed here)// or the format they present (as described in the comments).// The prefix is followed by a colon only when Llongfile or Lshortfile// is specified.// For example, flags Ldate | Ltime (or LstdFlags) produce,//// 2009/01/23 01:23:23 message//// while flags Ldate | Ltime | Lmicroseconds | Llongfile produce,//// 2009/01/23 01:23:23.123123 /a/b/c/d.go:23: messageconst (Ldate = 1 << iota // the date in the local time zone: 2009/01/23Ltime // the time in the local time zone: 01:23:23Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime.Llongfile // full file name and line number: /a/b/c/d.go:23Lshortfile // final file name element and line number: d.go:23. overrides LlongfileLUTC // if Ldate or Ltime is set, use UTC rather than the local time zoneLmsgprefix // move the "prefix" from the beginning of the line to before the messageLstdFlags = Ldate | Ltime // initial values for the standard logger)// A Logger represents an active logging object that generates lines of// output to an [io.Writer]. Each logging operation makes a single call to// the Writer's Write method. A Logger can be used simultaneously from// multiple goroutines; it guarantees to serialize access to the Writer.type Logger struct {outMu sync.Mutexout io.Writer // destination for outputprefix atomic.Pointer[string] // prefix on each line to identify the logger (but see Lmsgprefix)flag atomic.Int32 // propertiesisDiscard atomic.Bool}// New creates a new [Logger]. The out variable sets the// destination to which log data will be written.// The prefix appears at the beginning of each generated log line, or// after the log header if the [Lmsgprefix] flag is provided.// The flag argument defines the logging properties.func ( io.Writer, string, int) *Logger {:= new(Logger).SetOutput().SetPrefix().SetFlags()return}// SetOutput sets the output destination for the logger.func ( *Logger) ( io.Writer) {.outMu.Lock()defer .outMu.Unlock().out =.isDiscard.Store( == io.Discard)}var std = New(os.Stderr, "", LstdFlags)// Default returns the standard logger used by the package-level output functions.func () *Logger { return std }// Cheap integer to fixed-width decimal ASCII. Give a negative width to avoid zero-padding.func ( *[]byte, int, int) {// Assemble decimal in reverse order.var [20]byte:= len() - 1for >= 10 || > 1 {--:= / 10[] = byte('0' + - *10)--=}// i < 10[] = byte('0' + )* = append(*, [:]...)}// formatHeader writes log header to buf in following order:// - l.prefix (if it's not blank and Lmsgprefix is unset),// - date and/or time (if corresponding flags are provided),// - file and line number (if corresponding flags are provided),// - l.prefix (if it's not blank and Lmsgprefix is set).func ( *[]byte, time.Time, string, int, string, int) {if &Lmsgprefix == 0 {* = append(*, ...)}if &(Ldate|Ltime|Lmicroseconds) != 0 {if &LUTC != 0 {= .UTC()}if &Ldate != 0 {, , := .Date()itoa(, , 4)* = append(*, '/')itoa(, int(), 2)* = append(*, '/')itoa(, , 2)* = append(*, ' ')}if &(Ltime|Lmicroseconds) != 0 {, , := .Clock()itoa(, , 2)* = append(*, ':')itoa(, , 2)* = append(*, ':')itoa(, , 2)if &Lmicroseconds != 0 {* = append(*, '.')itoa(, .Nanosecond()/1e3, 6)}* = append(*, ' ')}}if &(Lshortfile|Llongfile) != 0 {if &Lshortfile != 0 {:=for := len() - 1; > 0; -- {if [] == '/' {= [+1:]break}}=}* = append(*, ...)* = append(*, ':')itoa(, , -1)* = append(*, ": "...)}if &Lmsgprefix != 0 {* = append(*, ...)}}var bufferPool = sync.Pool{New: func() any { return new([]byte) }}func () *[]byte {:= bufferPool.Get().(*[]byte)* = (*)[:0]return}func ( *[]byte) {// 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://go.dev/issue/23199if cap(*) > 64<<10 {* = nil}bufferPool.Put()}// Output writes the output for a logging event. The string s contains// the text to print after the prefix specified by the flags of the// Logger. A newline is appended if the last character of s is not// already a newline. Calldepth is used to recover the PC and is// provided for generality, although at the moment on all pre-defined// paths it will be 2.func ( *Logger) ( int, string) error {++ // +1 for this frame.return .output(0, , func( []byte) []byte {return append(, ...)})}// output can take either a calldepth or a pc to get source line information.// It uses the pc if it is non-zero.func ( *Logger) ( uintptr, int, func([]byte) []byte) error {if .isDiscard.Load() {return nil}:= time.Now() // get this early.// Load prefix and flag once so that their value is consistent within// this call regardless of any concurrent changes to their value.:= .Prefix():= .Flags()var stringvar intif &(Lshortfile|Llongfile) != 0 {if == 0 {var bool_, , , = runtime.Caller()if ! {= "???"= 0}} else {:= runtime.CallersFrames([]uintptr{}), := .Next()= .Fileif == "" {= "???"}= .Line}}:= getBuffer()defer putBuffer()formatHeader(, , , , , )* = (*)if len(*) == 0 || (*)[len(*)-1] != '\n' {* = append(*, '\n')}.outMu.Lock()defer .outMu.Unlock(), := .out.Write(*)return}func () {internal.DefaultOutput = func( uintptr, []byte) error {return std.output(, 0, func( []byte) []byte {return append(, ...)})}}// Print calls l.Output to print to the logger.// Arguments are handled in the manner of [fmt.Print].func ( *Logger) ( ...any) {.output(0, 2, func( []byte) []byte {return fmt.Append(, ...)})}// Printf calls l.Output to print to the logger.// Arguments are handled in the manner of [fmt.Printf].func ( *Logger) ( string, ...any) {.output(0, 2, func( []byte) []byte {return fmt.Appendf(, , ...)})}// Println calls l.Output to print to the logger.// Arguments are handled in the manner of [fmt.Println].func ( *Logger) ( ...any) {.output(0, 2, func( []byte) []byte {return fmt.Appendln(, ...)})}// Fatal is equivalent to l.Print() followed by a call to [os.Exit](1).func ( *Logger) ( ...any) {.Output(2, fmt.Sprint(...))os.Exit(1)}// Fatalf is equivalent to l.Printf() followed by a call to [os.Exit](1).func ( *Logger) ( string, ...any) {.Output(2, fmt.Sprintf(, ...))os.Exit(1)}// Fatalln is equivalent to l.Println() followed by a call to [os.Exit](1).func ( *Logger) ( ...any) {.Output(2, fmt.Sprintln(...))os.Exit(1)}// Panic is equivalent to l.Print() followed by a call to panic().func ( *Logger) ( ...any) {:= fmt.Sprint(...).Output(2, )panic()}// Panicf is equivalent to l.Printf() followed by a call to panic().func ( *Logger) ( string, ...any) {:= fmt.Sprintf(, ...).Output(2, )panic()}// Panicln is equivalent to l.Println() followed by a call to panic().func ( *Logger) ( ...any) {:= fmt.Sprintln(...).Output(2, )panic()}// Flags returns the output flags for the logger.// The flag bits are [Ldate], [Ltime], and so on.func ( *Logger) () int {return int(.flag.Load())}// SetFlags sets the output flags for the logger.// The flag bits are [Ldate], [Ltime], and so on.func ( *Logger) ( int) {.flag.Store(int32())}// Prefix returns the output prefix for the logger.func ( *Logger) () string {if := .prefix.Load(); != nil {return *}return ""}// SetPrefix sets the output prefix for the logger.func ( *Logger) ( string) {.prefix.Store(&)}// Writer returns the output destination for the logger.func ( *Logger) () io.Writer {.outMu.Lock()defer .outMu.Unlock()return .out}// SetOutput sets the output destination for the standard logger.func ( io.Writer) {std.SetOutput()}// Flags returns the output flags for the standard logger.// The flag bits are [Ldate], [Ltime], and so on.func () int {return std.Flags()}// SetFlags sets the output flags for the standard logger.// The flag bits are [Ldate], [Ltime], and so on.func ( int) {std.SetFlags()}// Prefix returns the output prefix for the standard logger.func () string {return std.Prefix()}// SetPrefix sets the output prefix for the standard logger.func ( string) {std.SetPrefix()}// Writer returns the output destination for the standard logger.func () io.Writer {return std.Writer()}// These functions write to the standard logger.// Print calls Output to print to the standard logger.// Arguments are handled in the manner of [fmt.Print].func ( ...any) {std.output(0, 2, func( []byte) []byte {return fmt.Append(, ...)})}// Printf calls Output to print to the standard logger.// Arguments are handled in the manner of [fmt.Printf].func ( string, ...any) {std.output(0, 2, func( []byte) []byte {return fmt.Appendf(, , ...)})}// Println calls Output to print to the standard logger.// Arguments are handled in the manner of [fmt.Println].func ( ...any) {std.output(0, 2, func( []byte) []byte {return fmt.Appendln(, ...)})}// Fatal is equivalent to [Print] followed by a call to [os.Exit](1).func ( ...any) {std.Output(2, fmt.Sprint(...))os.Exit(1)}// Fatalf is equivalent to [Printf] followed by a call to [os.Exit](1).func ( string, ...any) {std.Output(2, fmt.Sprintf(, ...))os.Exit(1)}// Fatalln is equivalent to [Println] followed by a call to [os.Exit](1).func ( ...any) {std.Output(2, fmt.Sprintln(...))os.Exit(1)}// Panic is equivalent to [Print] followed by a call to panic().func ( ...any) {:= fmt.Sprint(...)std.Output(2, )panic()}// Panicf is equivalent to [Printf] followed by a call to panic().func ( string, ...any) {:= fmt.Sprintf(, ...)std.Output(2, )panic()}// Panicln is equivalent to [Println] followed by a call to panic().func ( ...any) {:= fmt.Sprintln(...)std.Output(2, )panic()}// Output writes the output for a logging event. The string s contains// the text to print after the prefix specified by the flags of the// Logger. A newline is appended if the last character of s is not// already a newline. Calldepth is the count of the number of// frames to skip when computing the file name and line number// if [Llongfile] or [Lshortfile] is set; a value of 1 will print the details// for the caller of Output.func ( int, string) error {return std.Output(+1, ) // +1 for this frame.}
![]() |
The pages are generated with Golds v0.7.6. (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. |