Signal Handling Techniques
Signal Handling Strategies in Golang
1. Basic Signal Notification
func basicSignalHandling() {
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan,
syscall.SIGINT,
syscall.SIGTERM)
<-sigChan
fmt.Println("Signal received")
}
2. Selective Signal Handling
graph TD
A[Signal Received] --> B{Specific Signal?}
B --> |SIGINT| C[Custom Interrupt Handler]
B --> |SIGTERM| D[Graceful Shutdown]
B --> |Other| E[Default Handling]
3. Advanced Signal Management
func advancedSignalHandling() {
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan,
syscall.SIGINT,
syscall.SIGTERM,
syscall.SIGHUP)
for {
select {
case sig := <-sigChan:
switch sig {
case syscall.SIGINT:
fmt.Println("Interrupt received")
case syscall.SIGTERM:
fmt.Println("Termination signal")
return
case syscall.SIGHUP:
fmt.Println("Hangup signal")
}
}
}
}
Signal Handling Techniques Comparison
Technique |
Pros |
Cons |
Basic Notification |
Simple implementation |
Limited control |
Selective Handling |
Precise signal management |
More complex code |
Goroutine-based |
Non-blocking |
Requires careful synchronization |
Best Practices
- Always use buffered channels
- Handle multiple signals
- Implement graceful shutdown
- Use context for cancellation
Context-Based Signal Handling
func contextSignalHandling() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-sigChan
cancel()
}()
// Long-running task
select {
case <-ctx.Done():
fmt.Println("Shutting down gracefully")
}
}
LabEx Recommended Approach
At LabEx, we recommend a comprehensive signal handling strategy that:
- Uses buffered channels
- Implements context-based cancellation
- Provides clean shutdown mechanisms
Common Pitfalls to Avoid
- Blocking main goroutine
- Ignoring signal propagation
- Incomplete resource cleanup