Unlocking Go’s log Package: Simple, Flexible, and Concurrency‑Safe Logging
This article explains the importance of logging, outlines the Go standard library log package’s design highlights—simplicity, flexibility, concurrency safety, and customizability—describes its core Logger structure, shows how mutexes ensure thread‑safe writes, and provides practical code examples with guidance on extending functionality.
Design Highlights of the Go log Package
Simple API : Functions such as log.Println, log.Printf and log.Fatal let developers start logging with a single line of code.
Flexibility : log.New creates a custom Logger instance that can have its own prefix, output destination and flag configuration.
Concurrency safety : The internal Logger embeds a sync.Mutex, guaranteeing that concurrent calls from multiple goroutines do not interleave.
Customizability : Users can set the logger’s prefix, flags (date, time, file name, line number, etc.) and direct output to any io.Writer implementation, such as files, buffers or network connections.
Basic Structure and Usage
The core type is Logger. It stores three main fields – a prefix string, a flag bitmask that controls the header format, and an io.Writer that receives the formatted log line. The logger provides methods like Print, Println, Printf, Fatal and Writer for common logging scenarios.
How Concurrency Safety Is Implemented
Mutex protection : The Logger struct contains an embedded sync.Mutex named outMu. Every write operation – for example the Println or Printf path – locks this mutex before writing and unlocks it afterwards.
Lock/Unlock pattern : The lock is acquired at the beginning of the critical section (the call to out.Write) and released via defer to ensure the mutex is always released, even if an error occurs.
Example Implementation
type Logger struct {
outMu sync.Mutex // protects out during writes
out io.Writer // destination for log output
prefix atomic.Pointer[string] // line prefix, e.g. "INFO: "
flag atomic.Int32 // Ldate, Ltime, Lshortfile, etc.
isDiscard atomic.Bool // when true, output is suppressed
}
func (l *Logger) output(pc uintptr, calldepth int, appendOutput func([]byte) []byte) error {
if l.isDiscard.Load() {
return nil
}
now := time.Now()
prefix := l.Prefix()
flag := l.Flags()
var file string
var line int
if flag&(Lshortfile|Llongfile) != 0 {
if pc == 0 {
_, file, line, _ = runtime.Caller(calldepth)
} else {
fs := runtime.CallersFrames([]uintptr{pc})
f, _ := fs.Next()
file = f.File
if file == "" {
file = "???"
}
line = f.Line
}
}
buf := getBuffer()
defer putBuffer(buf)
formatHeader(buf, now, prefix, flag, file, line)
*buf = appendOutput(*buf)
if len(*buf) == 0 || (*buf)[len(*buf)-1] != '
' {
*buf = append(*buf, '
')
}
l.outMu.Lock()
defer l.outMu.Unlock()
_, err := l.out.Write(*buf)
return err
}
func (l *Logger) Writer() io.Writer {
l.outMu.Lock()
defer l.outMu.Unlock()
return l.out
}The code shows how the logger acquires outMu before writing the buffered log line, ensuring that only one goroutine can perform the write at any moment. The Writer method also locks the mutex to provide a safe reference to the underlying io.Writer.
Practical Takeaway
The Go standard library log package delivers a lightweight, concurrency‑safe logger that follows Go’s philosophy of simplicity and efficiency. For projects that need structured logging, higher performance, or advanced features, third‑party libraries such as zap or logrus can be considered.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Ops Development & AI Practice
DevSecOps engineer sharing experiences and insights on AI, Web3, and Claude code development. Aims to help solve technical challenges, improve development efficiency, and grow through community interaction. Feel free to comment and discuss.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
