Defer
Defer adalah mekanisme untuk menunda eksekusi fungsi hingga fungsi yang melingkupinya selesai. Defer sangat berguna untuk cleanup operations.
Contoh Masalah
Bagaimana cara:
- Memastikan resource dibersihkan
- Menangani cleanup operations
- Mengatur urutan eksekusi
Penyelesaian
package main
import (
"fmt"
"io"
"os"
"sync"
)
// 1. Basic file handling dengan defer
func writeToFile(filename string, content string) error {
// Open file
file, err := os.Create(filename)
if err != nil {
return err
}
defer file.Close() // Will be called when function returns
// Write content
_, err = io.WriteString(file, content)
return err
}
// 2. Multiple defers
func multipleDefers() {
fmt.Println("Start")
defer fmt.Println("First defer")
defer fmt.Println("Second defer")
defer fmt.Println("Third defer")
fmt.Println("End")
}
// 3. Defer dengan parameter evaluation
func parameterEvaluation() {
i := 0
defer fmt.Printf("Deferred i: %d\n", i)
i++
fmt.Printf("Final i: %d\n", i)
}
// 4. Defer dalam loop
func deferInLoop() {
for i := 0; i < 3; i++ {
defer fmt.Printf("Deferred %d\n", i)
}
}
// 5. Custom cleanup dengan defer
type Resource struct {
name string
mu sync.Mutex
}
func (r *Resource) Use() {
r.mu.Lock()
defer r.mu.Unlock()
fmt.Printf("Using resource: %s\n", r.name)
// Simulate work
for i := 0; i < 3; i++ {
fmt.Printf("Working with %s: step %d\n", r.name, i+1)
}
}
// 6. Panic recovery dengan defer
func mayPanic() {
defer func() {
if r := recover(); r != nil {
fmt.Printf("Recovered from panic: %v\n", r)
}
}()
panic("something went wrong")
}
// 7. Nested defer
func nestedDefer() {
fmt.Println("Entering outer function")
defer fmt.Println("Exiting outer function")
func() {
fmt.Println("Entering inner function")
defer fmt.Println("Exiting inner function")
fmt.Println("Inner function executing")
}()
fmt.Println("Outer function executing")
}
func main() {
// Contoh 1: File handling
fmt.Println("File Handling Example:")
err := writeToFile("test.txt", "Hello, World!")
if err != nil {
fmt.Printf("Error writing file: %v\n", err)
} else {
fmt.Println("File written successfully")
}
// Contoh 2: Multiple defers
fmt.Printf("\nMultiple Defers Example:\n")
multipleDefers()
// Contoh 3: Parameter evaluation
fmt.Printf("\nParameter Evaluation Example:\n")
parameterEvaluation()
// Contoh 4: Defer in loop
fmt.Printf("\nDefer in Loop Example:\n")
deferInLoop()
// Contoh 5: Resource cleanup
fmt.Printf("\nResource Cleanup Example:\n")
r := &Resource{name: "database"}
r.Use()
// Contoh 6: Panic recovery
fmt.Printf("\nPanic Recovery Example:\n")
mayPanic()
// Contoh 7: Nested defer
fmt.Printf("\nNested Defer Example:\n")
nestedDefer()
// Cleanup test file
os.Remove("test.txt")
}
Penjelasan Kode
Basic Defer
- Delay execution
- LIFO order
- Function completion
Common Uses
- File handling
- Lock/unlock
- Resource cleanup
Special Cases
- Parameter evaluation
- Nested defers
- Panic recovery
Output
File Handling Example:
File written successfully
Multiple Defers Example:
Start
End
Third defer
Second defer
First defer
Parameter Evaluation Example:
Final i: 1
Deferred i: 0
Defer in Loop Example:
Deferred 2
Deferred 1
Deferred 0
Resource Cleanup Example:
Using resource: database
Working with database: step 1
Working with database: step 2
Working with database: step 3
Panic Recovery Example:
Recovered from panic: something went wrong
Nested Defer Example:
Entering outer function
Entering inner function
Inner function executing
Exiting inner function
Outer function executing
Exiting outer function
Tips
- Gunakan defer untuk cleanup
- Perhatikan urutan eksekusi
- Evaluasi parameter saat defer
- Hindari defer dalam loop
- Defer untuk error handling