mirror of
https://github.com/nabbar/golib.git
synced 2025-12-24 11:51:02 +08:00
225 lines
8.1 KiB
Go
225 lines
8.1 KiB
Go
/*
|
|
* MIT License
|
|
*
|
|
* Copyright (c) 2025 Nicolas JUHEL
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
* copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*
|
|
*
|
|
*/
|
|
|
|
/*
|
|
Package ioutils provides a comprehensive suite of I/O utilities for Go applications,
|
|
offering enhanced functionality for file operations, stream management, and data flow control.
|
|
|
|
# Design Philosophy
|
|
|
|
The ioutils package is built around three core principles:
|
|
|
|
1. Safety: All operations include proper error handling and resource cleanup
|
|
2. Flexibility: Components can be combined to create complex I/O workflows
|
|
3. Performance: Optimized for both throughput and memory efficiency
|
|
|
|
# Architecture
|
|
|
|
The package is organized into a root-level utility and several specialized subpackages:
|
|
|
|
Root Package (ioutils)
|
|
├── PathCheckCreate - File/directory creation with permission management
|
|
│
|
|
├── aggregator - Thread-safe write aggregator that buffers and serializes concurrent writes to a single writer function
|
|
├── bufferReadCloser - io.Closer wrappers for bytes.Buffer and bufio types
|
|
├── delim - Buffered reader for reading delimiter-separated data streams
|
|
├── fileDescriptor - Cross-platform utilities for managing file descriptor limits
|
|
├── ioprogress - Thread-safe I/O progress tracking wrappers for monitoring read and write operations
|
|
├── iowrapper - Flexible I/O wrapper enabling customization and interception of I/O operations
|
|
├── mapCloser - Thread-safe, context-aware manager for multiple io.Closer instances
|
|
├── maxstdio - Standard I/O redirection and capture
|
|
├── multi - Thread-safe, adaptive multi-writer extending io.MultiWriter with advanced features
|
|
└── nopwritecloser - io.WriteCloser wrapper with no-op Close()
|
|
|
|
Each subpackage is designed to solve specific I/O challenges while maintaining
|
|
compatibility with standard library interfaces.
|
|
|
|
# Key Features
|
|
|
|
Path Management:
|
|
- Atomic file/directory creation
|
|
- Automatic parent directory creation
|
|
- Permission validation and correction
|
|
- Type checking (file vs directory)
|
|
|
|
Stream Processing:
|
|
- Buffered write aggregation
|
|
- Progress tracking
|
|
- Delimiter-based parsing
|
|
- Multiple source/destination handling
|
|
|
|
Resource Management:
|
|
- Automatic cleanup via defer patterns
|
|
- Closer collection management
|
|
- File descriptor lifecycle control
|
|
|
|
# Performance Characteristics
|
|
|
|
The package is optimized for:
|
|
- Low memory overhead through buffer pooling
|
|
- Minimal allocations in hot paths
|
|
- Concurrent-safe operations where needed
|
|
- Efficient permission checking
|
|
|
|
Benchmarks show:
|
|
- PathCheckCreate: ~100ns for existing paths with correct permissions
|
|
- Aggregator: 10x throughput improvement for concurrent writes
|
|
- BufferReadCloser: 50% memory reduction vs bytes.Buffer for large streams
|
|
|
|
# Limitations
|
|
|
|
1. Platform Dependencies:
|
|
- Permission handling varies between Unix and Windows
|
|
- File descriptor operations may require OS-specific handling
|
|
- Some permissions (e.g., write-only on Windows) have limited support
|
|
|
|
2. Concurrency:
|
|
- PathCheckCreate is not atomic for the same path across goroutines
|
|
- Subpackages provide their own concurrency guarantees
|
|
|
|
3. Error Handling:
|
|
- Does not use panic; all errors must be explicitly handled
|
|
- Some operations may partially succeed before returning an error
|
|
|
|
# Common Use Cases
|
|
|
|
Application Initialization:
|
|
|
|
// Ensure application directories exist
|
|
if err := ioutils.PathCheckCreate(false, "/var/app/data", 0644, 0755); err != nil {
|
|
return fmt.Errorf("data dir: %w", err)
|
|
}
|
|
|
|
// Create log file with proper permissions
|
|
if err := ioutils.PathCheckCreate(true, "/var/log/app.log", 0644, 0755); err != nil {
|
|
return fmt.Errorf("log file: %w", err)
|
|
}
|
|
|
|
Configuration Management:
|
|
|
|
// Create config directory structure
|
|
configPaths := []string{
|
|
"/etc/app/config",
|
|
"/etc/app/config/plugins",
|
|
"/etc/app/config/templates",
|
|
}
|
|
|
|
for _, path := range configPaths {
|
|
if err := ioutils.PathCheckCreate(false, path, 0644, 0750); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
Log File Rotation:
|
|
|
|
// Ensure log directory exists before rotation
|
|
logDir := filepath.Dir(logPath)
|
|
if err := ioutils.PathCheckCreate(false, logDir, 0644, 0755); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Create new log file
|
|
if err := ioutils.PathCheckCreate(true, logPath, 0644, 0755); err != nil {
|
|
return err
|
|
}
|
|
|
|
See subpackage documentation for advanced I/O operations including write
|
|
aggregation, progress tracking, and stream processing.
|
|
|
|
# Thread Safety
|
|
|
|
The root PathCheckCreate function is safe to call from multiple goroutines
|
|
for different paths. However, concurrent calls for the same path may result
|
|
in race conditions. Use external synchronization if needed.
|
|
|
|
Each subpackage documents its own concurrency guarantees.
|
|
|
|
# Error Handling
|
|
|
|
All functions return errors that can be inspected using standard error
|
|
handling patterns:
|
|
|
|
if err := ioutils.PathCheckCreate(true, path, 0644, 0755); err != nil {
|
|
if errors.Is(err, os.ErrPermission) {
|
|
// Handle permission error
|
|
} else if errors.Is(err, os.ErrNotExist) {
|
|
// Handle path error
|
|
} else {
|
|
// Handle other errors
|
|
}
|
|
}
|
|
|
|
Errors are wrapped to provide context about the operation that failed.
|
|
|
|
# Best Practices
|
|
|
|
1. Always check errors - this package never uses panic
|
|
2. Use appropriate permissions - follow least privilege principle
|
|
3. Clean up resources - use defer for closers
|
|
4. Consider platform differences - test on target OS
|
|
5. Validate paths - ensure paths are absolute when needed
|
|
|
|
# Migration Notes
|
|
|
|
When migrating from os package functions:
|
|
|
|
// Before
|
|
if err := os.MkdirAll(path, 0755); err != nil {
|
|
return err
|
|
}
|
|
|
|
// After - also handles permission updates
|
|
if err := ioutils.PathCheckCreate(false, path, 0644, 0755); err != nil {
|
|
return err
|
|
}
|
|
|
|
The PathCheckCreate function combines mkdir, permission checking, and type
|
|
validation in a single call.
|
|
|
|
# Related Packages
|
|
|
|
- os: Standard library file operations
|
|
- io: Standard library I/O interfaces
|
|
- filepath: Path manipulation utilities
|
|
- bufio: Buffered I/O operations
|
|
|
|
# Subpackage Overview
|
|
|
|
For detailed documentation, see individual subpackage docs:
|
|
|
|
- aggregator: Thread-safe write aggregator that buffers and serializes concurrent write operations to a single writer function
|
|
- bufferReadCloser: io.Closer wrappers for bytes.Buffer and bufio types with cleanup
|
|
- delim: Buffered reader for reading delimiter-separated data streams
|
|
- fileDescriptor: Cross-platform utilities for managing file descriptor limits in Go applications
|
|
- ioprogress: Thread-safe I/O progress tracking wrappers for monitoring read and write operations in real-time through customizable callbacks
|
|
- iowrapper: Flexible I/O wrapper that enables customization and interception of read, write, seek, and close operations on any underlying I/O object
|
|
- mapCloser: Thread-safe, context-aware manager for multiple io.Closer instances
|
|
- maxstdio: Standard I/O stream redirection and capture
|
|
- multi: Thread-safe, adaptive multi-writer that extends Go's standard io.MultiWriter with advanced features
|
|
- nopwritecloser: No-op Close() wrapper for io.Writer (delegates Write unchanged)
|
|
*/
|
|
package ioutils
|